On this page

For AI agents: a documentation index is available at /docs/llms.txt. Append .md to any page URL for markdown, or send Accept: text/markdown.

Proxy requests to Guides and Surveys

A reverse proxy routes Guides and Surveys traffic through a domain you own. The SDK keeps working when ad blockers, browser extensions, DNS filters, or regional firewalls block Amplitude domains. You run one proxy host, route three path patterns to three Amplitude hosts (four if you use the AI assistant), and point the SDK at it with a single proxyUrl option. Guides and Surveys APIs and static assets are latency-sensitive. Use an edge-hosted proxy, such as a CDN or edge function, if possible.

How routing works

Every Amplitude host that the SDK calls owns distinct paths, so one proxy host can route by path without rewriting it:

The /api/* rule is only required if you use the AI assistant. Without it, guides, surveys, and the Resource Center work normally through the proxy.

Each rule needs to:

  • Forward the full path and query string unchanged.
  • Send the Amplitude host, not your proxy host, as the Host header.
  • Allow GET, HEAD, OPTIONS, PUT, POST, PATCH, and DELETE on /sdk/* and /api/*. The SDK uses POST to save dismissal and completion state.
  • If you add the /api/* rule, stream its responses without buffering or compressing them. The AI assistant streams each answer as server-sent events over a long-lived POST request.

Use the wildcard patterns exactly as shown. Don't list individual paths like /sdk/v1/config. The SDK calls many endpoints under each prefix, including /sdk/v1/preview/config for preview mode, and a rule that lists specific paths breaks the endpoints it omits.

Choose a proxy host

You can serve the proxy from a dedicated subdomain or from a path on your app's domain:

  • Dedicated subdomain: For example, https://gs.example.com. The rules apply at the root of the subdomain. Use this with Cloudflare Workers, CloudFront, or NGINX.
  • Path on your app's domain: For example, https://app.example.com/gs. Each rule adds the /gs prefix to the incoming path and removes it before forwarding. Use this with framework rewrites, such as Next.js or Vercel, where the root paths would collide with your app's own routes.

Pick a neutral name. Ad blockers often match on words like analytics, tracking, telemetry, or amplitude in hostnames and paths.

Set up the proxy

The examples use US hosts. For the EU data center, replace each host with its EU equivalent from the routing table. If you don't use the AI assistant, leave out the parts marked as optional.

Create a Worker, paste this script, then attach a custom domain such as gs.example.com under Settings > Domains & Routes.

js
const UPSTREAMS = {
  sdk: "https://gs.amplitude.com",
  cdn: "https://cdn.amplitude.com",
  media: "https://engagement-static.amplitude.com",
  // Optional: only needed for the AI assistant
  api: "https://assistant-api.amplitude.com",
};

function upstreamFor(pathname) {
  if (pathname.startsWith("/sdk/")) return UPSTREAMS.sdk;
  if (pathname.startsWith("/engagement-browser/")) return UPSTREAMS.cdn;
  // Optional: only needed for the AI assistant
  if (pathname.startsWith("/api/")) return UPSTREAMS.api;
  return UPSTREAMS.media;
}

export default {
  async fetch(request) {
    const url = new URL(request.url);
    const target = new URL(
      url.pathname + url.search,
      upstreamFor(url.pathname),
    );
    return fetch(new Request(target, request));
  },
};

Your proxyUrl is https://gs.example.com.

If you use the AI assistant, confirm that your platform streams responses and allows requests to stay open for at least a few minutes on /api/*. Platforms that buffer responses deliver each answer in one block after the agent finishes.

Initialize the SDK with the proxy

Set proxyUrl to your proxy host:

js
engagement.init("API_KEY", {
  proxyUrl: "https://gs.example.com",
});

If you install Guides and Surveys as an Analytics Browser SDK plugin, pass the same option to the plugin: amplitude.add(window.engagement.plugin({ proxyUrl: "https://gs.example.com" })).

proxyUrl sets serverUrl, cdnUrl, mediaUrl, and chatUrl to the same value. To send one type of traffic elsewhere, set that option explicitly; explicit values take precedence over proxyUrl. On SDK versions that don't support proxyUrl, set serverUrl, cdnUrl, and mediaUrl to your proxy host instead, plus chatUrl if you use the AI assistant.

Test the proxy

Replace PROXY_URL with your proxyUrl and APIKEY with your project's API key. Each request returns HTTP status 200 OK when the proxy routes it correctly.

Test the Guides and Surveys API:

bash
curl -i 'PROXY_URL/sdk/v1/decide' -H 'Authorization: Api-Key APIKEY'

Test the SDK bundle:

bash
curl -I 'PROXY_URL/engagement-browser/prod/index.min.js.gz'

If you use the AI assistant, test the assistant API:

bash
curl -i 'PROXY_URL/api/chat/settings' -H 'Authorization: Api-Key APIKEY'

A 403 or 404 response from your proxy, rather than from Amplitude, usually means the request matched the wrong rule.

Troubleshooting common proxy issues

  • Preview mode doesn't work
    • Symptoms: Preview mode fails to load or display guides properly.
    • Cause: The /sdk/* rule lists specific paths, such as /sdk/v1/config, instead of the wildcard.
    • Solution: Use the /sdk/* wildcard. Preview mode calls /sdk/v1/preview/config.
  • Guides don't persist dismissal or completion state
    • Symptoms: Guides reappear in the next session after the user dismisses or completes them.
    • Cause: The /sdk/* rule doesn't allow POST, or it forwards your proxy host as the Host header.
    • Solution: Allow GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE on /sdk/* and send the Amplitude host as the Host header. In CloudFront, use the AllViewerExceptHostHeader origin request policy.
  • Images don't load in guides
    • Symptoms: Images appear broken or show placeholder icons.
    • Cause: The catch-all rule doesn't route to the image host, or the SDK doesn't use the proxy for media.
    • Solution: Route everything outside /sdk/*, /engagement-browser/*, and /api/* (if present) to engagement-static.amplitude.com or engagement-static.eu.amplitude.com, and set proxyUrl or mediaUrl.
  • The AI assistant doesn't answer, or the answer appears in one block
    • Symptoms: The chat window shows an error, stays empty, or displays the full answer after a long pause instead of streaming it word by word.
    • Cause: The /api/* rule is missing, so assistant requests reach the image host, or the proxy buffers or compresses the streamed response.
    • Solution: Add the /api/* rule and turn off buffering and compression on it. In CloudFront, set Compress objects automatically to No. In NGINX, set proxy_buffering off.
  • The SDK doesn't load
    • Symptoms: The browser console reports that the Engagement SDK bundle failed to load.
    • Cause: The /engagement-browser/* rule is missing or routes to the wrong host.
    • Solution: Route /engagement-browser/* to cdn.amplitude.com or cdn.eu.amplitude.com, then run the SDK bundle test.

For any other failure, open your browser's developer tools, filter the Network tab by your proxy host, and check which requests return 403, 404, or CORS errors. Compare each failing path to the routing table.

Was this helpful?