Skip to content

Site client

The site client is what a site’s own code calls: the site’s identity, forms, the storefront and its reviews, and analytics. It wraps the platform paths under /_platform/, with the same methods in a site’s Worker and in the browser. It needs no key: Digize knows which site a call comes from, and nothing the site sends can change that.

import { createSiteClient } from "@digize/sdk";
// In the browser, on a page of the site:
const digize = createSiteClient();
// In a site's Worker, with the visitor's request:
const forVisitor = createSiteClient({ request });
Option
request In a site’s Worker, the visitor’s Request. The client calls the platform paths on its origin, which is the site’s own hostname, and sends the visitor’s address (cf-connecting-ip), user agent and referer with each call, which the form and review limits and Turnstile use. The visitor’s cookies are never sent.
origin Where the platform paths are, such as https://shop.brightwave.com. Wins over request’s origin. Only the origin is used; a path after it is ignored.
fetch Used instead of the global fetch, such as in tests.
headers Sent with every call.

Without origin or request, a browser calls relative paths (/_platform/forms) on the page’s own hostname. Anywhere else there’s nothing to call relative paths on, and each call throws invalid saying to pass one.

Every fetch a site’s Worker makes goes through Digize’s Outbound Worker, which answers the platform paths on the site’s own hostname itself. Create a client per request from the visitor’s request:

src/index.ts
import { createSiteClient, handlePlatform, isDigizeError } from "@digize/sdk";
export default {
async fetch(request: Request): Promise<Response> {
// The browser's own calls to /_platform/… go on to Digize.
const platform = await handlePlatform(request);
if (platform) return platform;
const url = new URL(request.url);
const digize = createSiteClient({ request });
const slug = url.pathname.match(/^\/products\/([^/]+)$/)?.[1];
if (!slug) return new Response("Not found", { status: 404 });
try {
const { product, store } = await digize.store.product(slug);
return new Response(
`<h1>${product.name}</h1><p>From ${store.name}</p>`,
{ headers: { "content-type": "text/html; charset=utf-8" } },
);
} catch (error) {
if (isDigizeError(error, "not_found")) {
return new Response("No such product", { status: 404 });
}
throw error;
}
},
};

createSiteClient({ request }) also works with origin: "https://digize.com": Outbound answers the platform paths on the App Worker’s origin too, for the same site.

The SDK is an ES module, so a site’s front end imports it like any other package and its bundler (Vite, Astro, webpack and the rest) includes it. On a page of the site, createSiteClient() with no options calls the page’s own hostname:

src/product-page.ts
import { createSiteClient } from "@digize/sdk";
const digize = createSiteClient();
document.querySelector("#buy")?.addEventListener("click", async () => {
const variantId = (document.querySelector("#variant") as HTMLSelectElement).value;
const { url } = await digize.store.checkout({
lines: [{ variantId, quantity: 1 }],
successUrl: `${location.origin}/checkout/done`,
cancelUrl: location.href,
});
location.assign(url);
});

In the browser the client also fills in what the page knows: a form’s pageUrl, the UTM parameters and click ids in the page’s address as attribution, and a review request’s ?review= token.

A browser’s request for /_platform/forms on the site’s hostname goes to the site’s Worker like any other path. Outbound only answers the Worker’s own fetches, so the Worker passes the call on. handlePlatform(request) does it, and answers null for every other path:

const platform = await handlePlatform(request);
if (platform) return platform;

It passes on /_platform/context, /_platform/forms and the /_platform/store/… paths, with the body, the content type, the visitor’s address as x-forwarded-for, their user agent and referer, and none of their cookies. Digize’s answer comes back with its status and content type, cache-control: no-store, and a plain HTML form’s 303 redirect to a page on the site. The tracker’s paths (/_platform/t/…, /_platform/e) never reach the Worker: Digize answers those before it runs.

A site deployed without a Worker of its own gets Digize’s static site script, which does the same for every platform path, so the browser client works on a static site as it is.

A page on another hostname, such as a marketing site at www.brightwave.com with its shop at shop.brightwave.com, calls the shop’s platform paths with origin, and the shop’s Worker allows that origin:

// On www.brightwave.com
const shop = createSiteClient({ origin: "https://shop.brightwave.com" });
const { reviews } = await shop.store.reviews({ limit: 6 });
// In the shop's Worker
const platform = await handlePlatform(request, {
allowOrigins: ["https://www.brightwave.com"],
});
if (platform) return platform;

allowOrigins answers the browser’s OPTIONS preflight and adds access-control-allow-origin for those origins only. Analytics always go to the page’s own hostname.

const { workspaceId, siteId, hostname } = await digize.context();

context() answers who Digize says is calling: the workspace, the site, and the hostname the request came in on.

Method
context() The site’s workspace, site id and hostname.
forms.submit(form, fields, options) A form post, answered as a result with the field errors. See Forms.
forms.settings() The Turnstile site key forms render their widget with, and whether it runs on this hostname.
store.page(query), store.home(), store.product(slug), store.collection(handle, cursor), store.search(q, cursor) Storefront page data. See Storefront.
store.checkout(cart), store.checkoutStatus(checkoutId) Starting a checkout, and whether it was paid.
store.reviews(query), store.submitReview(review) The reviews widget’s reviews, and a review a visitor leaves.
analytics.track(name, props), analytics.pageview(options), analytics.flush() Analytics events, in the browser. See Analytics.

Every method but forms.submit and the analytics ones throws a DigizeError when Digize turns the call down or can’t be reached.