Mount /edgekit/ on your domain
Add rules to whatever serves your site (your CDN, load balancer or web server) so that requests to /edgekit/ on
your domain reach your tenant host. Your pages then call EdgeKit at relative paths such as /edgekit/v1/decide.
Before you start
Section titled “Before you start”- Your tenant host: EdgeKit gives it to your organization. The samples use
https://your-tenant-host. - Your site’s id: open the site from Delivery › Delivery › Sites. The id is the last part of the
page address:
site_examplein/delivery/sites/site_example. - HTTPS on your site: EdgeKit’s sign-in cookies are
Secure, and browsers do not store them for a page served over plain HTTP.
Route the paths
Section titled “Route the paths”| Request on your domain | Forward to https://your-tenant-host as |
|---|---|
/edgekit/v1/* |
The same path: /edgekit/v1/decide stays /edgekit/v1/decide |
/edgekit/a/* |
The path without /edgekit: /edgekit/a/t becomes /a/t |
/edgekit/i |
/i |
/edgekit/com.snowplowanalytics.snowplow/tp2 |
/com.snowplowanalytics.snowplow/tp2 |
The first rule carries the client API and decide. The other three carry analytics events. The EdgeKit tracker posts
to /edgekit/a/t by default
(EdgeKitTrackerOptions); the last two rows
are only for a tracker that sends to the standard tracker paths.
Leave every other path to your site. EdgeKit uses nothing outside /edgekit/ on your domain, so /v1/ on your own
domain stays yours.
Forward requests and responses unchanged
Section titled “Forward requests and responses unchanged”Forward to the tenant host:
- the method, the body and the query string;
Cookie, which carries the user’s sign-in session;Originand theSec-Fetch-*headers, which the origin check reads;x-edgekit-site-id, which selects the site. The browser client sends it on every request;Content-Type.
Set Host to the tenant host. Most forwarders do this when the target is a URL.
Return to the browser:
- the status code, including redirects. Do not follow them in the forwarder: some EdgeKit paths answer
302for the browser to follow; - every
Set-Cookieheader, each one separate; Cache-ControlandVary. Answers that depend on who is asking areno-store. The public site configuration at/edgekit/v1/id/configmay be cached for 5 minutes and varies onx-edgekit-site-id, so a cache in front of it must honourVary.
A forwarder in TypeScript
Section titled “A forwarder in TypeScript”The same rules as a fetch handler, for a server or edge runtime that takes one. It returns null for paths that are
not EdgeKit’s, so your own handler serves them.
const TENANT_HOST = 'https://your-tenant-host';
// Analytics paths reach the tenant host without the /edgekit prefix.const ANALYTICS_PREFIXES = [ '/edgekit/a/', '/edgekit/com.snowplowanalytics.snowplow/',];
function edgekitTarget(url: URL) { const { pathname, search } = url;
if (pathname.startsWith('/edgekit/v1/')) { return new URL(pathname + search, TENANT_HOST); }
if ( pathname === '/edgekit/i' || ANALYTICS_PREFIXES.some((prefix) => pathname.startsWith(prefix)) ) { return new URL(pathname.slice('/edgekit'.length) + search, TENANT_HOST); }
return null;}
export async function forwardToEdgeKit(request: Request) { const target = edgekitTarget(new URL(request.url));
if (!target) return null;
const headers = new Headers(request.headers);
// fetch sets Host from the target URL. headers.delete('host');
return fetch(target, { method: request.method, headers, body: ['GET', 'HEAD'].includes(request.method) ? undefined : await request.arrayBuffer(), // Hand redirects back to the browser. redirect: 'manual', });}What each /edgekit/v1 path carries
Section titled “What each /edgekit/v1 path carries”Most /edgekit/v1/ paths have a /v1/ twin on the tenant host. They differ in which credential they take.
The same contract as /v1
Section titled “The same contract as /v1”These answer exactly what their /v1/ path answers, with the same credentials:
| Path | What it is |
|---|---|
/edgekit/v1/id/* |
Sign-in and the user’s own record. Not /upstream/* |
/edgekit/v1/org/* |
The user organizations a user belongs to or administers |
/edgekit/v1/grants |
The signed-in user’s grants |
/edgekit/v1/newsletters/* |
Newsletter lists and where a user stands on each. Not /confirm or /unsubscribe |
The browser credential, where /v1 takes an API key
Section titled “The browser credential, where /v1 takes an API key”| Browser path | Server path |
|---|---|
/edgekit/v1/decide |
/v1/decide |
/edgekit/v1/gift-links |
/v1/gift-links |
/edgekit/v1/recommendations |
/v1/recommendations |
The browser path checks the site header and the origin, and never takes an API key. The server path takes a
site-pinned API key, and a browser cannot hold one. On /edgekit/v1/decide, a request body that names a userId is
refused with 403: in the browser, the user comes from the signed-in session only.
Only under /edgekit/v1
Section titled “Only under /edgekit/v1”/edgekit/v1/checkout, the purchase. There is no /v1/checkout.
Only on the tenant host
Section titled “Only on the tenant host”These have no /edgekit/v1/ path. Call them on the tenant host:
/v1/id/upstream/*: server calls with an API key./v1/newsletters/confirmand/v1/newsletters/unsubscribe: the confirmation and unsubscribe links in newsletter emails always point at the tenant host./v1/publications/{slug}/archive.jsonand/archive/*: a publication’s public archive./v1/webhooks/*: webhooks from your billing and messaging services./v1/content/syncand/v1/iglu/*: server calls with an API key./openapi.json,/docs,/v1/decide/openapi.jsonand/health.
Allow your site’s origins
Section titled “Allow your site’s origins”The origin check compares each browser request’s Origin with the site’s allowed origins. To set them:
- Open the site from Delivery › Delivery › Sites.
- In Settings, under Origins, enter every origin your pages are served from in Allowed, one per line:
scheme, host and port exactly, such as
https://www.example.com. - Save, then stage and deploy the draft on Delivery › Deployments › Versions. Requests read the deployed site, so the new list applies from that deploy.
The rules the check follows:
- Your own site’s origin belongs in the list. Browsers send
Originon aPOST, even a same-origin one. - Exact match only:
https://example.comandhttps://www.example.comare two origins, and so arehttp://andhttps://. An entry with a path or a trailing slash is refused when you save. - No wildcards: an entry containing
*never matches anything. - At most 50 entries per site.
- An empty list refuses every browser request that carries an
Origin. Delivery › Delivery › Sites marks such a site denies all. - A request with no
Originpasses only when the browser’sSec-Fetch-Siteheader says it is same-origin, or when it carries no fetch metadata at all, as a server or app request does.
A refused request answers 403 forbidden with no CORS headers. See
Troubleshooting.