Skip to content

Self-Host the Optimizely Snippet

⏱ 25 minutes advanced

By default, the Optimizely snippet loads from cdn.optimizely.com. This works well, but some organizations need more control. Self-hosting lets you:

  • Eliminate third-party domain requests — Avoid ad blockers that filter cdn.optimizely.com and satisfy strict Content Security Policies
  • Control caching — Set your own TTL instead of relying on Optimizely’s CDN cache headers
  • Bundle with your JavaScript — Combine the snippet with your application code to reduce HTTP requests
  • Pin to specific versions — Prevent automatic snippet updates from affecting production without your review
  • Comply with data residency requirements — Serve the snippet from infrastructure in your required region

The snippet is a self-contained JavaScript file that contains your project’s experiment configuration (the “datafile”), targeting rules, and the Optimizely client runtime. When it executes in the browser, it evaluates which experiments are active, buckets the visitor, and applies variation changes.

Optimizely updates the snippet whenever you publish changes to experiments. Self-hosting means you are responsible for fetching these updates and deploying them to your infrastructure.

The snippet URL for your project follows this pattern:

https://cdn.optimizely.com/js/{project_id}.js

Find your project ID in Settings > General in the Optimizely application.

Terminal window
curl -o optimizely-snippet.js "https://cdn.optimizely.com/js/YOUR_PROJECT_ID.js"

Use the Optimizely REST API to fetch the snippet programmatically.

Fetch the snippet via API
javascript
const fs = require('fs');
const https = require('https');

const PROJECT_ID = 'YOUR_PROJECT_ID';
const SNIPPET_URL = `https://cdn.optimizely.com/js/${PROJECT_ID}.js`;

https.get(SNIPPET_URL, (res) => {
  let data = '';
  res.on('data', (chunk) => data += chunk);
  res.on('end', () => {
    fs.writeFileSync('public/optimizely-snippet.js', data);
    console.log('Snippet downloaded successfully');
  });
}).on('error', (err) => {
  console.error('Download failed:', err.message);
});
python
import requests

PROJECT_ID = 'YOUR_PROJECT_ID'
SNIPPET_URL = f'https://cdn.optimizely.com/js/{PROJECT_ID}.js'

response = requests.get(SNIPPET_URL)
if response.status_code == 200:
    with open('public/optimizely-snippet.js', 'w') as f:
        f.write(response.text)
    print('Snippet downloaded successfully')
else:
    print(f'Download failed: {response.status_code}')

Module format note: The Node.js example above uses CommonJS (require). If your project uses ES modules, replace require with import:

import fs from 'fs';
import https from 'https';

Python dependency: The Python script requires the requests library. Install it with pip install requests if it is not already in your project dependencies.

Upload the downloaded snippet to your CDN or static hosting. Common setups:

PlatformDeployment method
AWS CloudFront + S3Upload to S3 bucket, invalidate CloudFront cache
CloudflareDeploy via Workers or upload to R2 storage
AkamaiPush to NetStorage origin, purge cache
FastlyUpload to origin, issue instant purge
Self-hosted NginxCopy to static file directory, reload config

Replace the default Optimizely snippet tag with your self-hosted URL.

<!-- Replace this -->
<script src="https://cdn.optimizely.com/js/YOUR_PROJECT_ID.js"></script>
<!-- With this -->
<script src="https://your-cdn.example.com/optimizely-snippet.js"></script>

Place the script tag in the <head> of your page, as early as possible, to minimize flicker.

The snippet changes every time you publish experiment modifications. Set up automation to keep your hosted version current.

  1. In Optimizely, navigate to Settings > Webhooks
  2. Add a webhook URL pointing to your build system (e.g., a CI/CD endpoint)
  3. Select the Datafile Updated event
  4. When triggered, your pipeline downloads the latest snippet and deploys it

If webhooks are not available, poll at a regular interval.

Terminal window
# Cron job — check every 5 minutes
*/5 * * * * curl -s -o /var/www/static/optimizely-snippet.js \
"https://cdn.optimizely.com/js/YOUR_PROJECT_ID.js"

For teams that require manual review before deploying snippet changes:

  1. Download the snippet to a staging environment
  2. Run integration tests against the updated snippet
  3. Promote to production after review
  4. Accept that experiments published during review are delayed until deployment

Configure your CDN to cache the snippet with an appropriate TTL.

StrategyTTLTrade-off
Aggressive caching1 hourFewer origin requests but slower experiment updates
Moderate caching5 minutesGood balance for most sites
No caching0 (pass-through)Instant updates but higher origin load

Add Cache-Control headers in your CDN configuration:

Cache-Control: public, max-age=300, s-maxage=300

If your site uses CSP headers, update them to allow the self-hosted snippet.

Content-Security-Policy: script-src 'self' https://your-cdn.example.com;

Remove https://cdn.optimizely.com from the CSP if you are fully self-hosted.

Self-hosting the snippet shifts operational responsibility from Optimizely to your team. Before committing, consider the ongoing costs:

  • Pipeline monitoring — Your update automation (webhook or cron) must be monitored. If it fails silently, your snippet becomes stale and experiments stop reflecting changes made in the Optimizely app.
  • CDN purge failures — A failed cache purge means visitors continue receiving an outdated snippet. Set up alerts on purge failures for your CDN provider and have a manual purge runbook ready.
  • Staleness detection — Add a monitoring check that compares the snippet version on your CDN against the latest version on cdn.optimizely.com. Alert if the versions diverge for more than your acceptable threshold (e.g., 15 minutes for webhook setups, or 2x your polling interval for cron setups).
  • On-call ownership — Someone on your team needs to be responsible for snippet freshness. If an experiment launch is blocked because the snippet did not update, the team needs a clear escalation path.

If the operational overhead outweighs the benefits, the default Optimizely-hosted snippet is a reliable alternative.

IssueCauseFix
Experiments not activatingStale snippet version on your CDNTrigger a cache purge and verify the latest snippet is deployed
Snippet blocked by CSPCSP does not allow your CDN domainAdd your CDN domain to the script-src directive
Webhook not firingWebhook URL unreachable from Optimizely serversVerify the URL is publicly accessible and returns a 200 response
Visual editor does not loadEditor expects the snippet on cdn.optimizely.comThe visual editor uses the Optimizely-hosted snippet regardless of your production setup — this is expected