Beginner Guide: Optimizely Web Experimentation Reverse Proxy with Cloudflare Workers and Vercel
Beginner Guide: Optimizely Web Experimentation Reverse Proxy with Cloudflare Workers and Vercel
Public-safe edition
This version has been sanitised for public documentation. Replace every value in
[BRACKETS]with your own environment-specific value when following the guide.Do not publish: real domains, project IDs, account IDs, email addresses, IP addresses, internal URLs, customer names, screenshots containing account information, API tokens, cookies, access tokens, or private configuration.
Last verified: 31 July 2026
Level: Beginner
Goal: Learn how to route Optimizely Web Experimentation requests through a first-party Cloudflare Worker hostname while keeping your Next.js website hosted on Vercel.
Public documentation placeholder legend
| Placeholder | Replace with |
|---|---|
[YOUR_DOMAIN] | Your own domain, e.g. example.com |
[YOUR_SNIPPET_ID] | Your Optimizely Web Experimentation snippet/project identifier |
[YOUR_ACCOUNT_ID] | Your Optimizely account ID |
[YOUR_PROJECT_ID] | Your Optimizely project ID |
[YOUR_WORKERS_SUBDOMAIN] | Your Cloudflare Workers workers.dev subdomain |
[YOUR_VERCEL_PREVIEW_URL] | Your exact Vercel preview URL, only if needed |
[CLOUDFLARE_EDGE_ADDRESS] | A runtime network address, if you choose to document one; normally omit it |
Tip: For a public tutorial, it is usually better to use placeholders even for values that are technically non-secret. This prevents readers from accidentally treating the author's environment as a copy-and-paste configuration.
1. What you are building
Your main website will remain on Vercel:
Visitor
│
▼
https://[YOUR_DOMAIN]
│
▼
Vercel
Optimizely requests will use a separate hostname connected to a Cloudflare Worker:
Visitor's browser
│
├── GET https://edge.[YOUR_DOMAIN]/js/YOUR_PROJECT_ID.js
│ │
│ ▼
│ Cloudflare Worker
│ │
│ ▼
│ https://cdn.optimizely.com/js/YOUR_PROJECT_ID.js
│
└── POST https://edge.[YOUR_DOMAIN]/v1/events
│
▼
Cloudflare Worker
│
▼
https://logx.optimizely.com/v1/events
The Worker has a simple job:
- Receive a request from the visitor's browser.
- Send that request to the correct Optimizely service.
- Return Optimizely's response to the browser.
This is called a reverse proxy because the browser communicates with your hostname, while the proxy communicates with Optimizely on the browser's behalf.
2. What this guide does not build
This guide does not:
- move your Next.js website from Vercel to Cloudflare;
- place a Cloudflare Worker in front of your entire website;
- use Next.js rewrites as the Optimizely proxy;
- configure Optimizely Edge Delivery;
- guarantee that every privacy browser or extension will allow Optimizely;
- replace your cookie-consent or privacy implementation.
Using a first-party hostname can reduce the likelihood of simple domain-list blocking. It is not a guarantee against every filtering technique.
You must continue to respect the visitor's consent choice. A reverse proxy changes the network route; it must not be used to bypass consent.
How to use this guide
Complete the steps in order. Every step contains a Success check. Do not continue to the next phase until that check passes.
Use these three milestones:
Milestone 1: The snippet loads through the temporary workers.dev address.
Milestone 2: The snippet loads through edge.[YOUR_DOMAIN].
Milestone 3: Browser events POST through edge.[YOUR_DOMAIN]/v1/events.
When something fails, troubleshoot the current milestone only. Do not change DNS, Next.js, and Optimizely settings at the same time.
3. Four terms to understand first
Origin
The server that owns the original resource.
In this guide:
- the snippet origin is
cdn.optimizely.com; - the event origin is
logx.optimizely.com; - your website origin is
[YOUR_DOMAIN].
Reverse proxy
A server that receives a browser request and forwards it to another server.
Your Cloudflare Worker will be the reverse proxy.
Worker
JavaScript code that runs on Cloudflare's network when a request reaches its assigned address.
Custom Domain
A hostname, such as edge.[YOUR_DOMAIN], that Cloudflare connects directly to a Worker. Cloudflare creates the required DNS record and certificate for the hostname.
4. The two Optimizely request types
Do not treat the setup as one large change. It has two separate parts.
| Part | Browser request | Purpose |
|---|---|---|
| Snippet delivery | GET request | Downloads the Optimizely JavaScript and configuration |
| Event tracking | POST request | Sends experiment decisions and conversions to Optimizely |
You will make snippet delivery work first. You will configure event tracking only after the snippet works.
5. Hostnames used in this guide
| Hostname | Purpose | What manages it |
|---|---|---|
[YOUR_DOMAIN] | Your main Next.js website | Vercel |
edge.[YOUR_DOMAIN] | Optimizely reverse-proxy endpoint | Cloudflare Worker Custom Domain |
edge.[YOUR_DOMAIN] is used instead of a hostname containing the word optimizely. This may reduce simple hostname-based filtering, but it does not guarantee that the requests will never be blocked.
A Worker Custom Domain is not the same as manually creating a normal CNAME and switching on the orange-cloud icon. Cloudflare creates and manages the DNS record when you attach the Custom Domain to the Worker.
Phase 1: Prepare the setup
Step 1: Leave your working Vercel website unchanged
Goal
Protect your working website while you learn.
What to do
Do not change the existing DNS record that currently makes this address work:
https://[YOUR_DOMAIN]
Do not add a Worker route to the main domain.
Do not use proxy.[YOUR_DOMAIN] for this exercise.
Why
The Optimizely proxy does not need to sit in front of your complete Vercel application. Keeping the Worker on a separate hostname isolates your experiment from the main website.
Vercel also warns that placing a reverse proxy in front of an entire Vercel project can affect firewall visibility and client-IP handling. This guide avoids that architecture.
Success check
Open:
https://[YOUR_DOMAIN]
Your website should load as it did before.
Do not continue if the main website is already broken. Fix the existing website first.
Step 2: Collect your Optimizely information
Goal
Find the identifiers you will need later.
What to do
In Optimizely Web Experimentation, open:
Settings → Implementation
Find your current project snippet. A standard snippet looks similar to this:
<script src="https://cdn.optimizely.com/js/123456789.js"></script>
Record the number before .js:
Project/snippet ID: 123456789
Also record:
Account ID: [YOUR_ACCOUNT_ID]
Project ID: [YOUR_PROJECT_ID]
The account ID is normally available under:
Account Settings → Plan
Why
- The snippet ID identifies the JavaScript file that your browser must download.
- Optimizely Support will need the account ID and project ID when you request the event-tracking-host change.
Success check
You should have these values written down:
Snippet URL:
Snippet or project ID:
Account ID:
Project ID:
Never install two Optimizely project snippets on the same page at the same time.
Phase 2: Build the Cloudflare Worker
Step 3: Create a basic Worker
Goal
Create the Cloudflare application that will become the reverse proxy.
What to do
In Cloudflare:
- Open Workers & Pages.
- Select Create application.
- Select Create Worker or the Hello World starting option shown in your dashboard.
- Name the Worker:
optimizely-proxy
- Deploy the starter Worker.
- Open the new Worker and select Edit Code.
Cloudflare should provide a temporary address similar to:
https://optimizely-proxy.[YOUR_WORKERS_SUBDOMAIN].workers.dev
Why
The temporary workers.dev address lets you test the code before connecting your own hostname.
Success check
Open the temporary Worker address. You should receive the starter response without an error.
Step 4: Replace the starter code with the proxy code
Goal
Teach the Worker where to send snippet requests and event requests.
What to do
Delete the starter Worker code and replace it with the following. You do not need to memorise every line before you begin; the four behaviours are explained immediately after the code.
const OPTIMIZELY_CDN = "https://cdn.optimizely.com";
const OPTIMIZELY_EVENTS = "https://logx.optimizely.com/v1/events";
// Only these websites may send browser event requests through the Worker.
const ALLOWED_ORIGINS = new Set([
"https://[YOUR_DOMAIN]",
"https://www.[YOUR_DOMAIN]",
// Add your exact Vercel preview URL here only when you need to test it.
// "https://your-project.vercel.app",
// Add localhost only when you need local testing.
// "http://localhost:3000",
]);
function isAllowedOrigin(origin) {
return origin !== null && ALLOWED_ORIGINS.has(origin);
}
function addCorsHeaders(headers, origin) {
if (!isAllowedOrigin(origin)) {
return;
}
headers.set("Access-Control-Allow-Origin", origin);
const currentVary = headers.get("Vary");
headers.set(
"Vary",
currentVary ? `${currentVary}, Origin` : "Origin"
);
}
function copyRequestHeaders(request) {
const headers = new Headers(request.headers);
// These cookies belong to your site and should not be forwarded to Optimizely.
headers.delete("Cookie");
// Do not forward credentials that may belong to your own application.
headers.delete("Authorization");
// Cloudflare sets the correct upstream Host value from the destination URL.
headers.delete("Host");
return headers;
}
export default {
async fetch(request) {
const incomingUrl = new URL(request.url);
const origin = request.headers.get("Origin");
try {
// A. Answer the browser's CORS permission check for event requests.
if (
request.method === "OPTIONS" &&
incomingUrl.pathname === "/v1/events"
) {
if (!isAllowedOrigin(origin)) {
return new Response("Origin not allowed", { status: 403 });
}
const headers = new Headers();
addCorsHeaders(headers, origin);
headers.set("Access-Control-Allow-Methods", "POST, OPTIONS");
headers.set(
"Access-Control-Allow-Headers",
request.headers.get("Access-Control-Request-Headers") ||
"Content-Type"
);
headers.set("Access-Control-Max-Age", "86400");
return new Response(null, {
status: 204,
headers,
});
}
// B. Forward all GET and HEAD paths to Optimizely's CDN.
if (request.method === "GET" || request.method === "HEAD") {
const upstreamUrl = new URL(
incomingUrl.pathname + incomingUrl.search,
OPTIMIZELY_CDN
);
const upstreamResponse = await fetch(upstreamUrl, {
method: request.method,
headers: copyRequestHeaders(request),
});
return new Response(upstreamResponse.body, {
status: upstreamResponse.status,
statusText: upstreamResponse.statusText,
headers: upstreamResponse.headers,
});
}
// C. Forward only POST /v1/events to Optimizely's event service.
if (
request.method === "POST" &&
incomingUrl.pathname === "/v1/events"
) {
if (!isAllowedOrigin(origin)) {
return new Response("Origin not allowed", { status: 403 });
}
const upstreamResponse = await fetch(OPTIMIZELY_EVENTS, {
method: "POST",
headers: copyRequestHeaders(request),
body: request.body,
});
const responseHeaders = new Headers(upstreamResponse.headers);
addCorsHeaders(responseHeaders, origin);
return new Response(upstreamResponse.body, {
status: upstreamResponse.status,
statusText: upstreamResponse.statusText,
headers: responseHeaders,
});
}
// D. Reject methods and event paths that this proxy does not need.
return new Response("Not found", { status: 404 });
} catch (error) {
console.error("Optimizely proxy error", error);
return new Response("Upstream proxy error", { status: 502 });
}
},
};
Select Deploy.
Why this code is structured this way
The code has four main behaviours:
GET or HEAD any path
→ Send it to cdn.optimizely.com using the same path
OPTIONS /v1/events
→ Answer the browser's cross-origin permission check
POST /v1/events
→ Send it to logx.optimizely.com/v1/events
Anything else
→ Return 404
Optimizely's reverse-proxy guidance specifies a wildcard GET route for the CDN. This is why the Worker preserves the complete path instead of allowing only /js/ and /public/.
The destination host is hard-coded. A visitor cannot use this Worker to choose an arbitrary external website.
The Worker removes Cookie before forwarding requests because cookies scoped to .[YOUR_DOMAIN] might otherwise be sent to edge.[YOUR_DOMAIN]. A direct browser request to cdn.optimizely.com would not receive those first-party cookies.
Why CORS is needed
These are different browser origins:
https://[YOUR_DOMAIN]
https://edge.[YOUR_DOMAIN]
They use different hostnames. The browser may therefore send an OPTIONS request before allowing the event POST. The CORS code permits only the website origins listed in ALLOWED_ORIGINS.
Success check
Cloudflare should show the new Worker version as deployed.
Step 5: Test snippet delivery on the temporary Worker address
Goal
Confirm the Worker can retrieve your real Optimizely snippet before changing DNS or Next.js.
What to do
Open this URL, replacing both placeholders:
https://optimizely-proxy.[YOUR_WORKERS_SUBDOMAIN].workers.dev/js/[YOUR_SNIPPET_ID].js
Example shape:
https://optimizely-proxy.example.workers.dev/js/123456789.js
Why
The request should follow this path:
Your browser
→ workers.dev address
→ Cloudflare Worker
→ cdn.optimizely.com
Testing here isolates the Worker from your custom-domain and Next.js configuration.
Success check
You should see minified JavaScript in the browser.
In Chrome DevTools → Network, the request should have:
Status: 200
Content-Type: JavaScript
Stop here if you receive
404,500,502, or a Cloudflare error. Do not connect the custom domain until this test works.
Phase 3: Connect your hostname to the Worker
Step 6: Check for an existing DNS record
Goal
Prevent a hostname conflict.
What to do
In Cloudflare, open:
[YOUR_DOMAIN] → DNS → Records
Search for:
edge
If a record already exists for edge.[YOUR_DOMAIN], remove it only when you are certain that it is not being used by another service.
Why
Cloudflare cannot create a Worker Custom Domain on a hostname that already has a conflicting CNAME record.
Success check
There should be no existing DNS record using edge.[YOUR_DOMAIN].
Step 7: Add the Worker Custom Domain
Goal
Give the Worker a first-party hostname under your domain.
What to do
Open:
Workers & Pages
→ optimizely-proxy
→ Settings
→ Domains & Routes
→ In domains search for chabu.chabu.com domain
→ Once found click next,you will see an option to enter a subdomain.
→ Enter only edge. ths will eventually be edge.[YOUR_DOMAIN].
Enter:
edge.[YOUR_DOMAIN]
Select Add Custom Domain.
Wait until Cloudflare shows the hostname as active.
Why
Cloudflare creates the required DNS record and TLS certificate. All paths under edge.[YOUR_DOMAIN] will now reach the Worker.
Do not manually create an additional CNAME for this hostname.
Success check
Cloudflare should show:
edge.[YOUR_DOMAIN] — Active
Step 8: Test the snippet through the custom domain
Goal
Confirm that DNS, TLS, the Worker, and the Optimizely CDN all work together.
What to do
Open:
https://edge.[YOUR_DOMAIN]/js/[YOUR_SNIPPET_ID].js
Why
The complete request path is now:
Your browser
→ edge.[YOUR_DOMAIN]
→ Cloudflare Worker
→ cdn.optimizely.com
Success check
You should see the minified Optimizely JavaScript and receive a 200 response.
Stop here if this fails. Your Next.js application should not be changed until this address works directly in the browser.
Phase 4: Connect the Next.js website
Step 9: Replace the existing Optimizely snippet URL
Goal
Make the website download Optimizely through your Worker instead of directly from Optimizely's CDN.
What to do
In your Next.js App Router project, open:
app/layout.tsx
Find and remove the existing Optimizely script tag, such as:
<script src="https://cdn.optimizely.com/js/[YOUR_SNIPPET_ID].js"></script>
Add the proxy version high inside <head>:
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<head>
<script src="https://edge.[YOUR_DOMAIN]/js/[YOUR_SNIPPET_ID].js"></script>
</head>
<body>{children}</body>
</html>
);
}
Replace [YOUR_SNIPPET_ID] with your real value.
Do not add async or defer during this learning exercise.
Deploy the change to Vercel.
Why
Optimizely recommends loading the Web Experimentation snippet synchronously and as high in <head> as practical to reduce visible flicker.
Before:
Browser → cdn.optimizely.com
After:
Browser → edge.[YOUR_DOMAIN] → Worker → cdn.optimizely.com
Important Next.js note
Next.js also provides the next/script component with strategy="beforeInteractive". That is a valid framework tool for critical early scripts, but it changes how Next.js schedules and preloads the resource. This beginner guide uses the direct synchronous <script> element so the loading behaviour stays closest to Optimizely's one-line installation guidance.
Next.js uses server rendering and hydration. Optimizely visual changes made before hydration can sometimes be overwritten by React. That is a separate integration topic from reverse proxying. Start with a simple test and verify that the variation remains visible after the page finishes loading.
Success check
The Vercel deployment should complete successfully.
Step 10: Verify that the website loads only the proxy snippet
Goal
Prove that the browser is using the new address and that you have not installed the snippet twice.
What to do
- Open an incognito browser window.
- Open
https://[YOUR_DOMAIN]. - Open Chrome DevTools.
- Select Network.
- Reload the page.
- Search for your snippet ID or
edge.[YOUR_DOMAIN].
Success check
You should see one request similar to:
GET https://edge.[YOUR_DOMAIN]/js/[YOUR_SNIPPET_ID].js
Status: 200
You should not see another project-snippet request to:
https://cdn.optimizely.com/js/[YOUR_SNIPPET_ID].js
In the Console, run:
window.optimizely
It should be defined rather than undefined.
Why
At this stage, you have proved that snippet delivery works through your reverse proxy.
Event requests may still go directly to logx.optimizely.com. That is expected until Optimizely changes the project build setting.
Step 11: Run a simple QA experiment
Goal
Confirm that the snippet can activate an experiment before changing event tracking.
What to do
Create or use a small QA experiment, for example:
Change one heading from “Welcome” to “Reverse Proxy Test”
Use Optimizely's normal QA or forced-variation process to view the variation.
Why
You are testing the first half of the architecture:
Snippet and configuration delivery
Do not troubleshoot event routing until the experiment itself activates correctly.
Success check
Confirm all three:
The proxy snippet returns 200.
window.optimizely is defined.
The QA variation appears and remains visible.
Phase 5: Route Optimizely events through the Worker
Step 12: Ask Optimizely to update the event-tracking host
Goal
Make the Web Experimentation snippet send experiment events to your Worker.
What to do
If you are still onboarding, contact your Onboarding Solutions Architect. Otherwise, contact Optimizely Support.
Send this request:
Hello,
Please update the EVENT_TRACKING_HOST build setting for the following
Optimizely Web Experimentation project:
Account ID: [YOUR_ACCOUNT_ID]
Project ID: [YOUR_PROJECT_ID]
Reverse-proxy base URL:
https://edge.[YOUR_DOMAIN]
The Worker accepts event requests at:
https://edge.[YOUR_DOMAIN]/v1/events
It forwards those POST requests to:
https://logx.optimizely.com/v1/events
Please confirm the exact event URL that will be generated in the project
snippet after the build-setting change.
Thank you.
Why
Changing the HTML script tag only changes where the JavaScript file is downloaded.
The JavaScript bundle still contains the event-tracking destination. Optimizely must update the EVENT_TRACKING_HOST build setting for the relevant Web Experimentation project.
Asking Optimizely to confirm the generated URL prevents you from guessing whether the setting expects only the hostname or a particular path format.
Success check
Optimizely confirms that the setting has been updated and the project snippet has been rebuilt.
Step 13: Verify event requests
Goal
Confirm that decision and conversion events are passing through the Worker.
What to do
After Optimizely confirms the update:
- Open a new incognito window.
- Open Chrome DevTools → Network.
- Load the experiment page.
- Perform the action used by your test metric.
- Search for:
v1/events
Success check
You should see:
POST https://edge.[YOUR_DOMAIN]/v1/events
The normal successful response from Optimizely's event endpoint is:
204 No Content
You should no longer see the browser sending the equivalent event directly to:
https://logx.optimizely.com/v1/events
Then verify that visitors and conversions appear in the appropriate Optimizely results page.
Phase 6: Compare normal and privacy-focused browsing
Step 14: Run a controlled comparison
Goal
Understand whether the first-party route changes blocking behaviour.
What to do
Test the same QA experiment in:
- normal Chrome without extensions;
- Chrome with the privacy extension you want to evaluate;
- the privacy-focused browser you want to evaluate.
For each test, record:
| Test | Snippet request | Event request | Variation shown | Event recorded |
|---|---|---|---|---|
| Normal Chrome | ||||
| Browser/extension test 1 | ||||
| Browser/extension test 2 |
Why
A Solutions Architect should test each part of the request flow instead of assuming that a first-party hostname solves every blocking method.
Success check
You can explain exactly which request succeeded or failed in each browser.
Troubleshooting guide
The custom-domain snippet returns 404
Check:
- the snippet ID is correct;
- the URL contains
/js/; - the Worker code is deployed;
edge.[YOUR_DOMAIN]is attached to the correct Worker.
Test the original Optimizely URL directly:
https://cdn.optimizely.com/js/[YOUR_SNIPPET_ID].js
If the original URL also returns 404, the snippet ID is probably incorrect.
The Worker returns 502
A 502 from this Worker means its request to Optimizely failed or the Worker threw an error.
Open:
Workers & Pages → optimizely-proxy → Logs
Look for:
Optimizely proxy error
window.optimizely is undefined
Check:
- the snippet request returned
200; - the response contains JavaScript rather than an error page;
- Content Security Policy allows
edge.[YOUR_DOMAIN]underscript-src; - the browser did not block the request;
- the snippet is not being loaded after an earlier JavaScript error.
The variation appears and then disappears
This may be a React or Next.js hydration issue rather than a reverse-proxy problem.
The proxy has succeeded if:
The snippet loaded from edge.[YOUR_DOMAIN] with status 200.
Investigate Optimizely's React SSR and hydration guidance separately.
The event request returns 403
The browser's exact Origin value is probably missing from ALLOWED_ORIGINS.
In DevTools, inspect the failed request's Request Headers and find:
Origin
Add that exact value to the Worker allowlist and deploy again.
Do not add a wildcard origin merely to hide the error.
The event request still goes directly to logx.optimizely.com
Possible causes:
- Optimizely has not updated
EVENT_TRACKING_HOSTyet; - the wrong project ID was updated;
- the snippet was not rebuilt after the setting changed;
- the browser or CDN is using an older cached snippet;
- the page is loading a different Optimizely snippet.
Compare the snippet ID in DevTools with the project that Optimizely Support updated.
The browser reports a Content Security Policy error
Your application may use a Content Security Policy.
The new hostname may need to be allowed in directives such as:
script-src
connect-src
Do not copy a broad CSP from another website. Update only the directives required by your application's existing policy.
Safe rollback
If you need to undo the application change, replace:
<script src="https://edge.[YOUR_DOMAIN]/js/[YOUR_SNIPPET_ID].js"></script>
with the original Optimizely snippet:
<script src="https://cdn.optimizely.com/js/[YOUR_SNIPPET_ID].js"></script>
Redeploy the Next.js application.
If Optimizely has already changed EVENT_TRACKING_HOST, ask Optimizely to restore the original setting as part of the rollback. Reverting only the HTML script URL does not automatically revert the event destination embedded in the snippet.
Production-readiness questions
The Worker above is suitable for learning and controlled testing. Before using a similar design for a customer production environment, review:
- separate development, staging, and production hostnames;
- exact origin allowlists for every environment;
- Cloudflare Worker logs and monitoring;
- rate limiting or abuse controls for
/v1/events; - Content Security Policy changes;
- cache behaviour and snippet update expectations;
- rollback ownership and procedure;
- privacy, legal, and consent requirements;
- whether the customer uses a standard, custom, or PCI-compliant snippet;
- testing for Next.js or React hydration behaviour;
- the customer's change-management and security-review process.
For a PCI-compliant snippet, the CDN host must be reviewed and changed from:
cdn.optimizely.com
to:
cdn-pci.optimizely.com
Do not make that change unless the Optimizely project actually uses the PCI-compliant snippet.
Standard snippet versus custom snippet
The main steps in this guide use a standard snippet:
https://cdn.optimizely.com/js/PROJECT_ID.js
A custom snippet normally uses an Optimizely /public/ACCOUNT_ID/... path. Optimizely's Cloudflare self-hosting documentation highlights custom snippets for additional account-level path verification.
The Worker in this guide preserves CDN paths, so a custom snippet can also be proxied using the equivalent path under edge.[YOUR_DOMAIN]. However, the correct custom-snippet URL should be copied from Optimizely and tested separately rather than guessed.
As a beginner, first complete the standard-snippet exercise. Then repeat it with a custom snippet as an advanced learning task.
What you should be able to explain after completing the guide
You should be able to answer these questions clearly:
- Why does the main Vercel website not need to pass through the Worker?
- What is the difference between snippet delivery and event tracking?
- Why is a Worker Custom Domain different from a normal manually created DNS record?
- Why must the Worker preserve wildcard CDN paths?
- Why must first-party cookies be removed before forwarding a request?
- Why does the event endpoint need CORS handling?
- Why must Optimizely update
EVENT_TRACKING_HOST? - Why does a
204event response count as success? - Why does a first-party reverse proxy reduce blocking risk without guaranteeing success?
- Why must consent behaviour remain unchanged?
These are the architectural explanations that matter in a Solutions Architect conversation—not only whether the code runs.
Official references
- Optimizely: Prevent Optimizely from being blocked by privacy-focused browsers and extensions
- Optimizely: Self-host the Optimizely snippet with Cloudflare
- Optimizely: Implement the one-line JavaScript snippet
- Optimizely: React server-side rendering and hydration
- Cloudflare: Worker Custom Domains
- Cloudflare: Modify a Worker response
- Cloudflare: Workers Fetch API
- Vercel: Reverse Proxy Servers and Vercel
- Next.js: Script Component
Public publication checklist
Before publishing this guide, search the Markdown for:
- your real domain name;
@symbols or email addresses;- real Optimizely account/project/snippet IDs;
- customer or employer names;
- internal hostnames or URLs;
- IP addresses;
- API keys, tokens, secrets, cookies, or authorization headers;
- screenshots containing browser history, account names, project names, IDs, or personal data;
- copied DevTools output containing request headers, cookies, query parameters, or identifiers.
If any appear, replace them with placeholders or remove them.
For a beginner-facing public guide, keep the learning flow isolated: test the Worker → test the custom domain → connect the website → test events → run QA → troubleshoot → review production readiness.