# Edge personalization

> This section explains how to configure and enable edge-side personalization on Netlify.

Source: https://docs.uniform.app/docs/integrations/cdn/netlify/netlify-edge-personalization

You can use Netlify Edge Functions to execute personalization on the edge. This approach gives you the user experience benefits of server-side rendering with the performance and scalability benefits of a CDN.

This section explains how to configure and enable edge-side personalization on Netlify.

> **Tip:**
>
> For more information about the benefits of executing personalization
> using Netlify Edge Functions, see the overview
> of [edge-side personalization](https://docs.uniform.app/docs/guides/personalization/edge-side-personalization).

## Before you start

> **Front-end framework use:**
>
> This guide is using Next.js as the front-end framework, however, this approach is compatible with any server-side render-able React or Vue meta-frameworks. Please [contact us](mailto:support@uniform.dev?subject=edge+personalization+framework) if you are using a different framework and need help putting it together.

You must have the following available to complete the instructions in this section:

1. The ability to [clone](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository) a GitHub repository.
2. [Node.js](https://nodejs.dev/) v16+ installed locally.
3. An application with [edge-side personalization activated](https://docs.uniform.app/docs/guides/personalization/activate-personalization#edge-side).
4. The application configured to be deployed to [Netlify](https://app.netlify.com). You can use their free tier if you don't have an account.
5. The Netlify CLI is installed and configured. See the [instructions](#configure-cli) on this page.
6. An npm access token from Uniform. Edge-side personalization requires private packages. If you don't have an access token, [contact us](mailto:support@uniform.dev?subject=Access+token+for+edge+personalization).

### Configure CLI

[Netlify CLI](https://docs.netlify.com/cli/get-started/) enables
you to send commands to Netlify without having to log into the
Netlify dashboard. In fact, some Netlify functionality isn't
available through the dashboard.

1. [Install](https://docs.netlify.com/cli/get-started/#installation) Netlify CLI with:

```bash
npm install netlify-cli -g
```

1. [Authenticate](https://docs.netlify.com/cli/get-started/#authentication) to Netlify with:

```bash
netlify login
```

Now you are ready to create the Netlify Edge Function, which executes the personalization instructions exposed by your front-end application.

### Pick your journey

This guide provides the following options to get started:

1. [Option 1](#option-1-quick-start-demo) - if you would like to start with a more feature rich demo to experience the power of edge-side personalization.
2. [Option 2](#option-2-add-edge-function-to-your-app) - if you would like to go through all the steps to add an edge function into your application and understand all the mechanics first.
3. [Option 3](#option-3-use-nextjs-starter) - if you are starting a new project and would like to begin with a "hello world" starter kit.

## Option 1: Quick start demo

This section guides you through the process of getting
a pre-built sample application deployed and running on
Netlify with personalization executed using Netlify
Edge Functions.

> **Before you start:**
>
> Don't use this application as a foundation or starting point
> to build your own application. This is a sample app designed
> to demonstrate edge-side personalization using Netlify Edge
> Functions.
>
> You must have the following available to complete
> the instructions in this section:
>
> 1. The ability to [clone](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository) a GitHub repository.
> 2. [Node.js](https://nodejs.dev/) v16+ installed locally.
> 3. The Netlify CLI installed and configured. See [instructions above](#configure-cli).
> 4. An npm access token from Uniform. Edge-side personalization requires private packages. If you don't have an access token, [contact us](mailto:support@uniform.dev?subject=Access+token+for+edge+personalization).

1. Open a terminal and enter the following:

   ```bash
   git clone https://github.com/uniformdev/examples.git
   ```

   and this:

   ```bash
   cd examples/context-edge-netlify
   ```
2. Ensure your npm access token is configured.

   > **About this step:**
   >
   > The sample code includes a file `.npmrc` that's set to
   > look for an environment variable `NPM_TOKEN`. You can set
   > an environment variable on your workstation to your npm
   > access token to meet this requirement.
   >
   > Another option is to set your npm access token directly in
   > the `.npmrc` file.
3. Enter the following command:

   ```bash
   npm install
   ```

   > **Beware:**
   >
   > If you get an error like the following, the problem is most
   > likely that either you do have your npm access token
   > configured correctly, or the access token has expired:
   >
   > ```
   > '@uniformdev/context-edge-netlify@^17.0.0' is not in this registry.
   > ```
4. Run `netlify dev`, which runs a local instance of Netlify, allowing you to experience the edge-side personalization before deploying it.
5. Open your browser to the following [URL](http://localhost:8888/?utm_campaign=unfrmconf).

   > You should see the personalized hero for "Call for papers."
6. In your browser, disable JavaScript. You should still see the personalized hero because personalization
   is happening in the Netlify Edge Function, not in the browser.
7. Enter the following command:

   ```bash
   netlify deploy --build --prod
   ```
8. After the application is deployed, you can visit the site
   to see personalization executed by Netlify Edge Functions.

## Option 2: Add Edge Function to your app

This section guides you through the process of activating
edge-side personalization on an existing web application
using Netlify Edge Functions.

### Step 1: Add Uniform Context into your app

Follow this guide to get your web app instrumented with Uniform Context SDK and configured to run in edge mode by following [this guide](https://docs.uniform.app/docs/guides/personalization/activate-personalization#edge-side).

> **Don't forget:**
>
> There are two crucial steps you must configure in order for the rest of the steps to work:
>
> 1. `NextCookieTransitionDataStore` is configured
> 2. `outputType="edge" is set on UniformContext:`<UniformContext outputType="edge" />`

### Step 2: Create your Edge Function

This section guides you through the process of building a
Netlify Edge Function that can execute Uniform personalization
instructions by explaining each step. It takes longer to
go through, but it will help you understand why each line
of code is needed.

1. Add the following environment variable to your workstation:

   | Name | Value |
   | --- | --- |
   | `NPM_TOKEN` | The npm access token from Uniform. |

   You can't set this value in the `.env` file. That file
   defines environment variables available within your app,
   while this environment is needed by another app (such as npm).

   You can set the environment variable to be system wide
   or just active in your current terminal.
2. Add the `.npmrc` file to the root of your application. This file ensures you can access the private packages required for edge-side personalization:

   ```shell
   //registry.npmjs.org/:_authToken=${NPM_TOKEN}
   engine-strict = true
   ```
3. Add the following package that includes the SDK to execute personalization via Netlify Edge Functions:

   ```bash
   npm install @uniformdev/context-edge-netlify
   ```
4. Add the following packages as dev dependencies to add cross-platform utility to copy files and run multiple npm scripts (this is optional if you'd like to manage the `copy:deno` npm script differently):

   ```bash
   npm install shx --save-dev
   npm install npm-run-all --save-dev
   ```
5. Add the following two npm scripts to `package.json`:

   ```json
       "copy:deno": "shx cp node_modules/@uniformdev/context-edge-netlify/dist/index.deno.js lib/uniform",
       "postinstall": "run-s copy:deno"
   ```

   Netlify Edge Functions run in the [Deno runtime](https://docs.netlify.com/netlify-labs/experimental-features/edge-functions/api/#runtime-environment)
   instead of Node.js. The package [@uniformdev/context-edge-netlify](https://sdk.uniform.app/context-edge-netlify)
   is Deno-compatible. The file in this package must be packaged
   with the Edge Function during the build process. This script
   copies the file to a place where it can be picked up at build-time.
6. Run the following command to copy the deno file to expected location:

   ```bash
   npm run copy:deno
   ```

   Create an empty `context-middleware.ts` file under `/netlify/edge-functions` folder.
7. Add the following imports:

   ```ts
   import {
     createEdgeContext,
     createUniformEdgeHandler,
   } from "../../lib/uniform/index.deno.js";
   import manifest from '../../contextManifest.json' assert { type: 'json' };
   // @ts-ignore: deno imports failing next build
   import type { Context } from "netlify:edge";
   ```

   This import statement assumes the name and location of your
   [Uniform manifest](https://docs.uniform.app/docs/guides/classification/manifest).
   If you file is in another location, you will need to change
   this statement.
8. Add the edge function body:

   ```ts
   export default async (request: Request, netlifyContext: Context) => {
     const IGNORED_PATHS = /\/.*\.(ico|png|jpg|jpeg|svg|css|js|json)(?:\?.*|$)$/g;
     if (request.method.toUpperCase() !== "GET" || request.url.match(IGNORED_PATHS)) {
       return await netlifyContext.next({ sendConditionalRequest: true });
     }
     // this creates the context object that has controls how the personalization process works.
     const context = createEdgeContext({
       manifest,
       request,
     });
     // This code creates the component that makes a request
     // to the origin and executes any personalization instructions in the response.
     const originResponse = await netlifyContext.next();
     const handler = createUniformEdgeHandler();
     // This code uses the proxy edge handler to make a request to the 
     // origin and execute the personalization instructions in the response.
     const { processed, response } = await handler({
       context,
       request,
       response: originResponse,
     });
     if (!processed) {
       return response;
     }
     return new Response(response.body, {
       ...response,
       headers: {
         // ...response.headers, Symbol cannot be destructured
         'Cache-Control': 'no-store, must-revalidate',
         'Content-Type': 'text/html; charset=utf-8', // To apply automatic deno compression, more info https://deno.com/deploy/docs/compression
         Expires: '0',
       },
     });
   };
   ```

   > **Note:**
   >
   > The Netlify Edge Function will be applied to all paths.
   > (This isn't a requirement. it's simply the way this
   > example is implemented.) Therefore, the function will need
   > to know which paths it should evaluate and which it should
   > not. The paths that match this expression are known to be
   > static files that have no personalization instructions in
   > them.
   >
   > The function passes control back to Netlify if the request that
   > isn't an [HTTP GET](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET)
   > or if it matches the ignored path expression. This means the
   > Netlify Edge Function won't try to execute personalization
   > instructions for the request.

### Step 3: Deploy your application

1. Add the following file:

   ```text
   [[plugins]]
   package = "@netlify/plugin-nextjs"
   [[edge_functions]]
   path = "/*"
   function = "context-middleware"
   ```

   > **Note:**
   >
   > Netlify uses this [file](https://docs.netlify.com/configure-builds/file-based-configuration/)
   > during the build and deployment process. This file provides
   > the following instructions to Netlify:
   >
   > - Use the [Next.js plugin](https://github.com/netlify/netlify-plugin-nextjs) during the build process.
   > - Route all requests to the specified Edge Function.
2. Enter the following command to do a production build and deployment of the site:

   ```bash
   netlify deploy --build --prod
   ```

   During the build process you will see log messages in the console.
3. In Netlify, navigate to **Deploys**, where you will see your application was deployed:

   ![](https://docs.uniform.app/images/integrations/cdn/netlify/personalization/deploys.png)
4. Click the deployment and you will see the edge functions were deployed:

   ![](https://docs.uniform.app/images/integrations/cdn/netlify/personalization/deploy-summary.png)
5. After the application is deployed, you can visit the site
   to see personalization executed by Netlify Edge Functions.

You can confirm personalization is running in Netlify if you
have personalization based on a query-string parameter.
Disable JavaScript on your browser and then view a page
with personalization. If you see personalized content,
you know the personalization was executed in Netlify.

> **Next steps:**
>
> Now that you have Netlify delivering edge-side personalization,
> you might want to take advantage of another feature available
> when you run personalization using Netlify Edge Functions:
> [location-based personalization](./add-geo-personalization).

## Option 3: Use Next.js starter

If you are kicking off a new project using Next.js, consider using this option.

> **Before you start:**
>
> You must have the following available to complete
> the instructions in this section:
>
> 6. The ability to [clone](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository) a GitHub repository.
> 7. [Node.js](https://nodejs.dev/) v16+ installed locally.
> 8. The Netlify CLI installed and configured. See the [instructions](#configure-cli) on this page.
> 9. An npm access token from Uniform. Edge-side personalization requires private packages. If you don't have an access token, [contact us](mailto:support@uniform.dev?subject=Access+token+for+edge+personalization).

### Step 1: Get started locally

1. Open a terminal and enter the following:

   ```bash
   git clone https://github.com/uniformdev/examples.git
   ```

   and get into the new directory:

   ```bash
   cd examples/context-edge-netlify
   ```
2. Ensure your npm access token is configured.

   > **Note:**
   >
   > The sample code includes a file `.npmrc` that's set to
   > look for an environment variable `NPM_TOKEN`. You can set
   > an environment variable on your workstation to your npm
   > access token to meet this requirement.
   >
   > Another option is to set your npm access token directly in
   > the `.npmrc` file.
3. Run `npm install` Enter the following command:

   > **Beware:**
   >
   > If you get an error like the following, the problem is most
   > likely that either you do have your npm access token
   > configured correctly, or the access token has expired:
   >
   > ```
   > '@uniformdev/context-edge-netlify@^17.0.0' is not in this registry.
   > ```
4. Run `netlify dev`, which runs a local instance of Netlify, allowing you to experience the edge-side personalization before deploying it:
5. Open your browser with http://localhost:8888/?utm_campaign=launch.

   > You should see the personalized hero matching the signal that evaluates when utm_campaign=launch is on the HTTP request.
6. In your browser, disable JavaScript. You should still see the personalized hero because personalization
   is happening in the Netlify Edge Function, not in the browser.

### Step 2: Deploy this app to your own Netlify account

Run this command to build and deploy this app to production:

```bash
   netlify deploy --build --prod
```

After the application is deployed, you can visit the site to see personalization executed by Netlify Edge Functions.

### Step 3: Wire this app to your own Uniform project

You must have access to a Uniform team with the ability to create new projects. If you are an active customer or a partner, please get in touch with your Uniform team administrator colleague and ask for an invite.

If you are not sure or your company does not have a Uniform team, you can request a sandbox [here](https://uniform.dev/try?utm_source=docs).

1. If that's your first time creating a team, your first project will have the Hello World starter already installed.
2. Head over to the Project Integrations -> Hello World
3. Scroll to the section where steps 1 through 4 are displayed and click on the "Generate environment variables" button.
4. Paste this environment variables into your `.env` file instead of the demo environment variables.

Now you are connected to your own Uniform project. You can now re-deploy it.
