# Cloudflare

By implementing a reverse proxy using Cloudflare Workers, you're serving Didomi's SDK and API assets through your own domain.

* Enhance performance by leveraging Cloudflare's edge caching.
* Maintain brand consistency and reduce reliance on third-party domains.
* Potentially improve compliance with privacy regulations by controlling SDK delivery.

This setup involves configuring a Cloudflare Worker to proxy requests to Didomi's CDN, ensuring proper handling of headers and caching as per Didomi's [guidelines](https://developers.didomi.io/cmp/web-sdk/custom-domain/self-hosting).

This guide explains how to configure Cloudflare Workers to create a reverse proxy that serves the Didomi Consent notice from your own domain. Two implementation options are available based on requirements:

[Choose your implementation](#choose-your-implementation)

[Implementation guide](#implementation-guide)

## Choose your implementation

### Option A: Use a subdomain

To implement a reverse proxy on a subdomain, you will first create a Cloudflare Worker with simple routing logic, then configure route triggers to activate the Worker for your domain. The Worker directly proxies `/api/*` and `/*` requests to Didomi's servers without URL transformation.

<figure><img src="https://1703900661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LDh8ZWDZrXs8sc4QKEQ%2Fuploads%2Fgit-blob-7ff31555cd646372fe56d2501569e2473053193d%2FServer-side%20Setup%20Miro%20(5).jpg?alt=media" alt=""><figcaption></figcaption></figure>

* **Customer Usage**: `/api/*` and `/*` paths directly
* **Architecture**: Cloudflare Worker with direct routing
* **Implementation**: Simple path routing with minimal URL transformation

### Option B: Use the main domain

To implement a reverse proxy on the main domain, you will first create a Cloudflare Worker that handles URL transformation (with (`/consent`), then configure a route trigger for `/consent/*` paths. The Worker removes the `/consent/` prefix before proxying requests to Didomi's servers.

<figure><img src="https://1703900661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LDh8ZWDZrXs8sc4QKEQ%2Fuploads%2Fgit-blob-ed49cb07df2dcc68df45e96d3a31e9a1d3f252db%2FServer-side%20Setup%20Miro%20(4).jpg?alt=media" alt=""><figcaption></figcaption></figure>

* **Customer Usage**: `/consent/*` prefix for all CMP requests
* **Architecture**: Cloudflare Worker with URL transformation
* **Implementation**: URL rewriting and advanced processing

### Domain vs Subdomain Trade-offs

When implementing a reverse proxy for the Didomi SDK and its API events, you need to choose between using your main domain or a dedicated subdomain. This choice has important implications for Safari's cookie restrictions.

For more information, see this [trade-off matrix](https://developers.didomi.io/api-and-platform/domains/reverse-proxy/..#domain-vs-subdomain-implementation) to select the implementation that suits your requirements.

## Implementation guide

[Option A: Use a subdomain](#option-a-use-a-subdomain-1)

[Option B: Use the main domain](#option-b-use-the-main-domain-1)

### Option A: Use a subdomain

#### Step 1: Create Cloudflare Worker

* In the left-hand sidebar, click on **Workers & Pages**.
* Click on **Create** and then **Hello world** (to start from scratch)
* In the **Name** field, enter `didomi-direct-proxy` (or any name you want)
* Click on **Deploy** and then **Edit code**
* Enter the following [code](https://github.com/didomi/boilerplate-cloudflare-reverse-proxy-didomi-cmp/blob/main/index.js) (`index.js`) and click on **Deploy**

The `index.js` file enables the Cloudflare Worker to:

* Proxy SDK requests from `/*` to `https://sdk.privacy-center.org/`.
* Proxy API requests from `/api/*` to `https://api.privacy-center.org/`.
* Remove cookies and sets the `X-Forwarded-For` header with the client's IP.
* Return a 404 response for other paths.

#### Step 2: Create Route Triggers

{% hint style="warning" %}
*Direct path routing* option, which occupies the main path, works only with a subdomain dedicated to the Didomi CMP.
{% endhint %}

* Navigate to your domain and click on **Workers Routes**
* Click on **Add route**
* Add two routes:

  **Route 1: SDK Route**

  ```
  YOUR_SUB_DOMAIN_NAME/*
  ```

  **Route 2: API Route**

  ```
  YOUR_SUB_DOMAIN_NAME/api/*
  ```
* Select the worker `didomi-direct-proxy` for both routes and **Save**

### Option B: Use the main domain

#### Step 1: Create a Cloudflare Worker

*A Worker is a serverless function that executes custom code at Cloudflare's edge, allowing you to intercept and modify HTTP requests and responses for tasks like proxying, caching, or rewriting content.*

* In the left-hand sidebar, click on **Workers & Pages**.\
  ![](https://1703900661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LDh8ZWDZrXs8sc4QKEQ%2Fuploads%2Fgit-blob-65cfaaba7f56aa7b96ddb47f426dd1f7c44ad97d%2FGroup_4.jpg?alt=media)
* Click on **Create** and then **Hello world** (to start from scratch)\
  ![](https://1703900661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LDh8ZWDZrXs8sc4QKEQ%2Fuploads%2Fgit-blob-e408154f4dc7e4a9d69d88554b793dd440c927bb%2FGroup_2.jpg?alt=media)
* In the **Name** field, enter `didomi-consent-loader`
* Click on **Deploy** and then **Edit code**\
  ![](https://1703900661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LDh8ZWDZrXs8sc4QKEQ%2Fuploads%2Fgit-blob-f1b2bfcdc9f69c493426fe3a612debe120f9fd6f%2FGroup_5.jpg?alt=media)
* Enter the following code and click on **Deploy**\
  ![](https://1703900661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LDh8ZWDZrXs8sc4QKEQ%2Fuploads%2Fgit-blob-51be98940d6c2a6cf4debdc34e53030d7baa795a%2FGroup_8.jpg?alt=media)

This [script](https://github.com/didomi/boilerplate-cloudflare-reverse-proxy-didomi-cmp/blob/main/index.js):

* Proxies SDK requests from `/consent/` to `https://sdk.privacy-center.org/`.
* Proxies API requests from `/consent/api` to `https://api.privacy-center.org/`.
* Removes cookies and sets the `X-Forwarded-For` header with the client's IP.
* Returns a 404 response for other paths.

```jsx
export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);
    const path = url.pathname;
    const clientIP = request.headers.get("CF-Connecting-IP") || "";

    // Define base URLs
    const sdkBase = "<https://sdk.privacy-center.org>";
    const apiBase = "<https://api.privacy-center.org>";

    // Determine if the request is for the SDK or API
    const isSDKRequest = path.startsWith("/consent/") && !path.startsWith("/consent/api");
    const isAPIRequest = path.startsWith("/consent/api");

    if (isSDKRequest) {
      // Construct the target URL for the SDK
      const targetPath = path.replace("/consent", "");
      const targetURL = new URL(sdkBase + targetPath);
      targetURL.search = url.search;

      // Prepare headers
      const headers = new Headers(request.headers);
      headers.delete("Cookie");
      headers.set("X-Forwarded-For", clientIP);

      // Fetch from Didomi's CDN
      const response = await fetch(targetURL.toString(), {
        method: request.method,
        headers: headers
      });

      // Clone and return the response
      return new Response(response.body, {
        status: response.status,
        statusText: response.statusText,
        headers: response.headers
      });
    }

    if (isAPIRequest) {
      // Construct the target URL for the API
      const targetPath = path.replace("/consent/api", "");
      const targetURL = new URL(apiBase + targetPath);
      targetURL.search = url.search;

      // Prepare headers
      const headers = new Headers(request.headers);
      headers.delete("Cookie");
      headers.set("X-Forwarded-For", clientIP);

      // Fetch from Didomi's API
      const response = await fetch(targetURL.toString(), {
        method: request.method,
        headers: headers,
        body: request.body
      });

      // Clone and return the response
      return new Response(response.body, {
        status: response.status,
        statusText: response.statusText,
        headers: response.headers
      });
    }

    // Return 404 for other requests
    return new Response("Not found", { status: 404 });
  }
};

```

#### 2. Create a Route trigger

*A Trigger, specifically a Route in this context, defines the URL pattern that determines when your Worker should run; it connects your Worker to specific paths on your domain, ensuring it activates only for matching requests.*

* Navigate to your domain and click on **Workers Routes**\
  ![](https://1703900661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LDh8ZWDZrXs8sc4QKEQ%2Fuploads%2Fgit-blob-0dfae0e4592e4545fede4662390453d0b5c880ed%2FGroup_6.jpg?alt=media)
* Click on Add route\
  ![](https://1703900661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LDh8ZWDZrXs8sc4QKEQ%2Fuploads%2Fgit-blob-547309c10ae0e26afe5c0de459203c16aa159f51%2FGroup_1.jpg?alt=media)
* Enter the route (or *URL pattern that determines when your Worker should run)*

  ```jsx
  YOUR_DOMAIN_NAME/consent/*
  ```

  ![](https://1703900661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LDh8ZWDZrXs8sc4QKEQ%2Fuploads%2Fgit-blob-9248a37f6ae9c6a4c7aa7f5d562a052b1df29846%2FGroup_7.jpg?alt=media)
* Select the worker `didomi-consent-loader` and **Save**

***

### Troubleshooting

#### Common Issues

**404 Not Found**

* Verify Worker routes are configured correctly
* Check if request path matches expected patterns
* Ensure Worker is deployed and active

**Worker Errors**

* Check Cloudflare dashboard for Worker logs
* Verify Worker code syntax is correct
* Ensure proper error handling in Worker

**CMP Not Loading**

* Verify `didomiConfig` paths match your routing option
* Check that API\_KEY and NOTICE\_ID are correct
* Ensure HTTPS is used for all requests

**CORS Issues**

* Cloudflare Workers handle CORS automatically
* Verify response headers are forwarded correctly
* Check if additional CORS headers are needed

#### Debug Steps

1. **Check Worker Logs** in Cloudflare dashboard
2. **Test direct URLs** to verify routing works
3. **Verify DNS** points to Cloudflare
4. **Check browser console** for JavaScript errors
5. **Test with curl** to isolate issues

***

{% hint style="success" %}
After setting up your reverse proxy, update your Didomi SDK snippet to use your own domain instead of `privacy-center.org`. This ensures that the Didomi assets are served from your configured domain.

For more information, see the guide to [serving Didomi assets from your domain](https://developers.didomi.io/cmp/web-sdk/serve-didomi-assets-from-your-domain#configure-the-sdk).
{% endhint %}
