# Cloudflare Edge-side personalization

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

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

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

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

> **Before you start:**
>
> You must have the following available to complete
> the instructions in this section:
>
> 1. Administrator access to [Cloudflare Dashboard](https://dash.cloudflare.com/). You can use their free tier if you don't have an account.
> 2. Ability to [clone](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository) a GitHub repository.
> 3. [Node.js](https://nodejs.dev/) v16+ installed locally.
> 4. An application with [edge-side personalization activated](https://docs.uniform.app/docs/guides/personalization/activate-personalization#edge-side).
> 5. 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

[Cloudflare Wrangler](https://developers.cloudflare.com/workers/wrangler/install-and-update/) is
a CLI enables you to send commands to Cloudflare without having
to log into the Cloudflare dashboard. Entering commands on the CLI
is faster than having to navigate through a lot of different
screens in the dashboard.

1. [Install](https://developers.cloudflare.com/workers/wrangler/install-and-update/#install-wrangler) Wrangler.
2. [Authenticate](https://egghead.io/lessons/cloudflare-install-and-configure-the-cloudflare-workers-cli-wrangler) to Cloudflare.

> **Next steps:**
>
> Now you are ready to create the Cloudflare Worker, which is
> the component that executes the personalization instructions
> exposed by your front-end application.

## Write Cloudflare Worker code

You have two options for writing the Cloudflare Worker. You can
build it from scratch or use a functional example provided by Uniform.

**Steps**

> **Tip:**
>
> This section guides you through the process of building a
> Cloudflare Worker 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. Clone the following repository:

   ```
   https://github.com/cloudflare/worker-typescript-template
   ```
2. Add the following environment variable to your workstation:

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

   > **About this step:**
   >
   > 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.
3. Add the following file to the root of the repository:

   ```shell
   //registry.npmjs.org/:_authToken=${NPM_TOKEN}
   engine-strict = true
   ```

   > **About this step:**
   >
   > This file ensures you can access the private packages
   > required for edge-side personalization.
4. Add the following packages:

   ```
   @uniformdev/context-edge
   @uniformdev/context-edge-cloudflare
   ```
5. Add the following package as dev dependencies:

   ```
   @uniformdev/cli
   ```

   > **About this step:**
   >
   > The Uniform CLI is used to download the [Uniform manifest](https://docs.uniform.app/docs/guides/classification/manifest) during the build process.
6. Add the following to the file `tsconfig.json`:

   ```json
   "sourceMap": true,
   "esModuleInterop": true,
   "resolveJsonModule": true,
   "types": [
   ```

   > **About this step:**
   >
   > To keep this example simple and self-contained, the [Uniform manifest](https://docs.uniform.app/docs/guides/classification/manifest)
   > is included with the Cloudflare Worker. This means that any
   > time the manifest changes, the Cloudflare Worker must be
   > re-deployed. Uniform [webhooks](https://docs.uniform.app/docs/guides/webhooks)
   > can be used to automate this process.
7. Add the following to the file `package.json`:

   ```json
   ...
   "scripts": {
     "download:manifest": "uniform context manifest download --output ./src/context-manifest.json",
     "build": "webpack",
     "format": "prettier --write  '*.{json,js}' 'src/**/*.{js,ts}' 'test/**/*.{js,ts}'",
     "lint": "eslint --max-warnings=0 src && prettier --check '*.{json,js}' 'src/**/*.{js,ts}' 'test/**/*.{js,ts}'",
     "test": "jest --config jestconfig.json --verbose"
   },
   ...
   ```

   > **About this step:**
   >
   > This script uses the Uniform CLI to download the Uniform manifest to a local file.
8. Replace the code in the file `src/handler.ts` with the following:

   ```ts
   import { createEdgeContext } from '@uniformdev/context-edge'
   import { createCloudflareProxyEdgeHandler } from '@uniformdev/context-edge-cloudflare'
   import { ManifestV2 } from '@uniformdev/context'
   ```
9. Add the following code:

   ```ts
   import manifest from "./context-manifest.json";
   ```
10. Add the following code:

    ```ts
    export async function handleRequest(request: Request): Promise<Response> {
    }
    ```

    > **About this step:**
    >
    > This is the function that runs when the Cloudflare Worker
    > is invoked.
11. Add the following code:

    ```ts
    export async function handleRequest(request: Request): Promise<Response> {
      //@ts-ignore
      if (!ORIGIN_URL) {
        console.error('ORIGIN_URL environment is not defined')
        return new Response('Configuration Error', {
          status: 500,
        })
      }
    }
    ```

    > **About this step:**
    >
    > This adds validation logic to ensure the origin has been
    > identified. The Cloudflare Worker makes a request to the
    > origin to retrieve the markup with the personalization
    > instructions.
12. Add the following code:

    ```ts
    export async function handleRequest(request: Request): Promise<Response> {
      //@ts-ignore
      if (!ORIGIN_URL) {
        console.error('ORIGIN_URL environment is not defined')
        return new Response('Configuration Error', {
          status: 500,
        })
      }
      const handler = createCloudflareProxyEdgeHandler()
    }
    ```

    > **About this step:**
    >
    > This code creates the component that makes a request to the
    > origin and executes any personalization instructions in the
    > response.
13. Add the following code:

    ```ts
    export async function handleRequest(request: Request): Promise<Response> {
      //@ts-ignore
      if (!ORIGIN_URL) {
        console.error('ORIGIN_URL environment is not defined')
        return new Response('Configuration Error', {
          status: 500,
        })
      }
      const handler = createCloudflareProxyEdgeHandler()
      const context = createEdgeContext({
        request,
        manifest: manifest as ManifestV2,
      })
    }
    ```

    > **About this step:**
    >
    > This creates the context object that has controls how the personalization process works.
14. Add the following code:

    ```ts
    export async function handleRequest(request: Request): Promise<Response> {
      //@ts-ignore
      if (!ORIGIN_URL) {
        console.error('ORIGIN_URL environment is not defined')
        return new Response('Configuration Error', {
          status: 500,
        })
      }
      const handler = createCloudflareProxyEdgeHandler()
      const context = createEdgeContext({
        request,
        manifest: manifest as ManifestV2,
      })
      const { response } = await handler({
        context,
        request,
        //@ts-ignore
        originUrl: new URL(`https://${ORIGIN_URL}`).origin,
      })
      return response
    }
    ```

    > **About this step:**
    >
    > This code uses the proxy edge handler to make a request to the
    > origin, execute the personalization instructions in the response,
    > and return a response using the personalized results.

**Complete**

> **Tip:**
>
> This section gets you to having a Cloudflare Worker that can
> execute Uniform personalization instructions as quickly as
> possible. It doesn't explain each line of code.

1. Open a terminal and enter the following:

   ```
   git clone https://github.com/uniformdev/examples.git
   cd examples/context-edge-cloudflare-worker
   ```
2. Ensure your npm access token is configured properly.

   > **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:

   ```
   npm install
   ```

   > **About this step:**
   >
   > If you get an error like the following, the problem is most
   > likely that either you don't have your npm access token
   > configured correctly, or the access token has expired:
   >
   > ```
   > '@uniformdev/context-edge@^17.0.0' is not in this registry.
   > ```

## Configure Cloudflare Worker

1. Create a file `.env` with the following environment variables:

   | Variable name | Value |
   | --- | --- |
   | `UNIFORM_PROJECT_ID` | The Uniform project whose manifest is retrieved. |
   | `UNIFORM_API_KEY` | The Uniform API key used to retrieve the manifest. |
   | `UNIFORM_CLI_BASE_EDGE_URL` | Set to `https://eu.uniform.global` for EU region teams. |
   | `UNIFORM_CLI_BASE_URL` | Set to `https://eu.uniform.app` for EU region teams. |
2. In the file `wrangler.toml`, you must set the value for
   `account_id`. This must match your Cloudflare account ID
   You can retrieve this value by entering the following
   command on the CLI:

   ```
   wrangler whoami
   ```
3. In the file `wrangler.toml`, you must set an environment
   variable to identify the origin (such as the web server
   that's hosting your front-end application). You must
   add a new section to the file:

   ```
   [vars]
   ORIGIN_URL = "!!! YOUR ORIGIN URL !!!"
   ```

   > **About this step:**
   >
   > While the variable name suggests this value should be a URL,
   > it really must be the host name for the origin. For example,
   > if the origin is located at `https://some-origin.com`, the
   > value should be `some-origin.com`.

## Run Cloudflare Worker locally

You can use Wrangler to run the Cloudflare Worker locally.
This enables you to test and debug without having to deploy
to Cloudflare.

1. Enter the following command on the CLI:

   ```
   wrangler dev
   ```

   > **About this step:**
   >
   > This starts a local web server that hosts the Cloudflare Worker.
2. Open your browser to the endpoint shown in the console.

## Deploy Cloudflare Worker

1. Enter the following commands on the CLI:

   ```
   wrangler build
   wrangler publish
   ```

   > **About this step:**
   >
   > These commands build and publish your Cloudflare Worker to
   > Cloudflare.

> **Next steps:**
>
> Now that you have Cloudflare delivering edge-side personalization,
> you might want to take advantage of another feature available when
> you run personalization on Cloudflare: [location-based personalization](./cloudflare-user-location).
