Web SDK reference
The Origamy Web SDK ships in two parts, following the Segment/RudderStack pattern: a tiny
snippet you paste into <head> that stubs the API and queues calls, and the full engine
(analytics.min.js, ~25 KB gzipped) the snippet loads asynchronously from
https://cdn.origamy.io. Your page never blocks on analytics.
The API is Segment-compatible: if you have existing analytics.track(...) instrumentation, the
call signatures carry over unchanged.
Installation
Section titled “Installation”Paste the snippet from the Quickstart into your <head>.
Calls made before the engine arrives are queued and replayed in order.
load(writeKey, config?)
Section titled “load(writeKey, config?)”Initializes the SDK. Must be called before events are delivered; calls made earlier are queued.
await origamy.load("YOUR_WRITE_KEY", { apiHost: "https://events.origamy.io", // where events are delivered cdnHost: "https://cdn.origamy.io", // where plugin bundles load from flushInterval: 10000, // ms between automatic flushes maxQueueSize: 20, // events per batch before an early flush retryLimit: 3, // delivery attempts per batch debug: false, // verbose console logging autoTrack: { clicks: { enabled: true }, // see Auto-tracking below pages: { enabled: true }, },});| Option | Default | Description |
|---|---|---|
apiHost |
https://events.origamy.io |
Ingestion endpoint. Point this at your own gateway on a self-hosted (BYOD) data plane. |
cdnHost |
https://cdn.origamy.io |
Host device-mode plugin bundles are loaded from. |
flushInterval |
10000 |
How often (ms) the queue flushes to /v1/batch. |
maxQueueSize |
20 |
Queue flushes early once it holds this many events. |
retryLimit |
3 |
Failed batches retry with exponential backoff up to this many attempts. |
debug |
false |
Logs every event, flush, and retry to the console. |
autoTrack |
off | Opt-in automatic page and click tracking. |
Event methods
Section titled “Event methods”All five methods share the same optional last argument, options:
{ context?: object, // merged into the event's context timestamp?: string, // ISO-8601 override (for late/imported events) anonymousId?: string, // override the stored anonymous ID integrations?: { [destination: string]: boolean }, // per-event routing}See the Event spec for what each event looks like on the wire.
track(eventName, properties?, options?)
Section titled “track(eventName, properties?, options?)”Records an action the user performed. Name events in Object Action title case
("Order Completed", not "order-completed") — downstream destinations expect it.
origamy.track("Order Completed", { orderId: "12345", amount: 99.99, currency: "USD",}, { integrations: { GoogleAnalytics: false }, // skip GA for this event});identify(userId?, traits?, options?)
Section titled “identify(userId?, traits?, options?)”Ties the current visitor to a known user and records traits. Traits persist locally and merge
across calls. Calling identify with no userId updates traits on the current identity.
origamy.identify("user_123", { email: "ada@example.com", name: "Ada Lovelace", plan: "premium",});page(name?, properties?, options?)
Section titled “page(name?, properties?, options?)”Records a page view. The SDK fills in url, path, title, referrer, and search
automatically; anything you pass is merged on top.
origamy.page("Pricing", { experiment: "pricing-v2" });group(groupId, traits?, options?)
Section titled “group(groupId, traits?, options?)”Associates the current user with an account, company, or team.
origamy.group("company_456", { name: "Acme Corp", plan: "enterprise", employees: 100,});alias(userId, previousId?, options?)
Section titled “alias(userId, previousId?, options?)”Links two identities — typically the pre-signup anonymous ID to the new user ID — so identity
resolution can merge their history. previousId defaults to the stored anonymous ID.
origamy.alias("user_123");Auto-tracking
Section titled “Auto-tracking”Both surfaces are off by default and opt-in via load() config.
Clicks
Section titled “Clicks”Emits an Element Clicked track event when the user clicks an element carrying a
data-origamy-event attribute (or a custom selector). Deliberately not track-everything —
opt-in per element keeps your event stream high-signal.
origamy.load("KEY", { autoTrack: { clicks: { enabled: true } } });<button data-origamy-event="Upgrade Clicked">Upgrade</button>| Option | Default | Description |
|---|---|---|
enabled |
false |
Turn click auto-tracking on. |
selector |
[data-origamy-event] |
CSS selector matched against the click target and its ancestors. |
Auto-fires page() on initial load, back/forward navigation, and SPA route changes
(history.pushState/replaceState are patched and restored on destroy()).
| Option | Default | Description |
|---|---|---|
enabled |
false |
Turn page auto-tracking on. |
skipInitial |
false |
Skip the auto event on first load if you call page() explicitly at boot. |
Middleware — use(fn)
Section titled “Middleware — use(fn)”Middleware runs on every event before delivery. Return the (possibly modified) event, or null
to drop it. Async middleware is supported.
// Enrich every eventorigamy.use((event) => { event.context.appVersion = "1.2.3"; return event;});
// Drop internal trafficorigamy.use((event) => { if (event.type === "track" && event.event.startsWith("Internal ")) return null; return event;});Plugins (device-mode destinations)
Section titled “Plugins (device-mode destinations)”Plugins load a destination’s native script in the browser and forward events to it directly.
Which plugins load is controlled by your source’s destination configuration in the Origamy
dashboard, fetched from /v1/config at load time.
Built-in plugins: Google Analytics and Mixpanel.
Register a custom plugin before or after load():
origamy.registerPlugin("CustomDestination", () => ({ name: "CustomDestination", initialize(config) { // load vendor script, init client }, track(event) { // forward the event }, identify(event) {},}));Use the per-event integrations option to skip a destination for a single event.
Plugin scripts load from cdnHost at /integrations/<name>/<version>/index.js. The SDK
accepts only path-safe names and versions from the configuration, and when a destination’s
config carries an integrity value (a sha384-… Subresource Integrity hash for that build)
it is set on the script tag with crossorigin="anonymous", so a tampered CDN file is refused
by the browser.
Delivery, batching, and retries
Section titled “Delivery, batching, and retries”- Events queue in memory and flush to
POST /v1/batcheveryflushIntervalms, or earlier oncemaxQueueSizeevents accumulate. - Failed batches retry with exponential backoff, up to
retryLimitattempts. - On page unload, the SDK drains the queue with
navigator.sendBeacon(falling back to a synchronous XHR) so trailing events aren’t lost. - Requests authenticate with your write key — see Ingestion API.
Web push
Section titled “Web push”origamy.webPush subscribes the browser to push notifications from your journeys and
broadcasts. Connect the Web Push provider under Channels first, copy its VAPID public
key, and host the service worker. Then, from a
user gesture:
const subscription = await origamy.webPush.subscribe({ vapidPublicKey: "YOUR_VAPID_PUBLIC_KEY", serviceWorkerPath: "/origamy-sw.js", // default // registration: existingRegistration, // reuse a service worker you already have});It resolves to the PushSubscription, or null when the browser has no push support or the
person declined. It never throws.
| Method | Description |
|---|---|
webPush.subscribe(options) |
Asks permission, registers the service worker, subscribes, and registers the device with Origamy. |
webPush.unsubscribe() |
Unsubscribes the browser and removes the device from Origamy. |
webPush.getSubscription() |
The current subscription, or null. |
webPush.permission() |
"granted", "denied", "default", or "unsupported". |
webPush.isSupported() |
Whether the browser has service workers, the Push API and notifications. |
The device is registered with a Device Created or Updated event that goes to Origamy only —
never to device-mode plugins. Afterwards the SDK keeps it current by itself:
- on page load it re-sends a subscription the browser rotated, or one older than a week;
- after
identify()with a different person, it moves the device to them; reset()unregisters the device for the person signing out, and it stays unregistered until someone identifies again;- if notifications are blocked in browser settings, or the browser drops the subscription, the device is removed.
Utility methods
Section titled “Utility methods”| Method | Description |
|---|---|
ready(callback) |
Runs the callback once the SDK is loaded (immediately if it already is). |
reset() |
Clears the stored user ID, traits, and anonymous ID — call on logout. Also unregisters this browser’s push subscription for the person signing out. |
getAnonymousId() |
Returns the current anonymous ID. |
getUserId() |
Returns the identified user ID, or null. |
isLoaded() |
true once load() has completed. |
arePluginsLoaded() |
true once device-mode plugins have initialized. |
destroy() |
Tears down timers, listeners, and history patches. Mostly useful in tests and SPAs that hot-swap the SDK. |
Identity storage
Section titled “Identity storage”The anonymous ID, user ID and traits are kept in localStorage, falling back to a cookie and
then to memory. Cookies are written with SameSite=Lax, and with Secure on HTTPS pages.
Message and anonymous IDs come from the Web Crypto API (crypto.randomUUID, or
getRandomValues on older browsers).
Browser support
Section titled “Browser support”Modern evergreen browsers (Chrome, Firefox, Safari 11+, Edge). The SDK has zero runtime
dependencies, uses no eval, and is CSP-compatible.
