Skip to content

Install + identify

The browser SDK does two things: capture the referral token when a visitor arrives through a partner link (and keep it alive across sessions), and stitch that visitor to a user account when they sign up or log in. Revenue events are reported server-side — never from the browser.

Install

Terminal window
npm install @openpartner/sdk
import { OpenPartner } from '@openpartner/sdk';
export const op = OpenPartner.init({
apiUrl: 'https://app.openpartner.dev/api/t/<your-workspace>',
});

apiUrl is your workspace’s API base:

DeploymentapiUrl
Hostedhttps://app.openpartner.dev/api/t/<your-workspace>
Hosted, white-label domainhttps://portal.yourbrand.com/api
Self-hostedhttps://openpartner.yourbrand.com (your API URL)

The SDK ships ESM and CJS bundles, has zero runtime dependencies, and is ~4 KB gzipped.

Capture is automatic

init() runs capture immediately: it reads ?cref=… from the landing URL (a visitor’s first arrival from a partner link) or the _cref first-party cookie (subsequent pages), and stashes the token in localStorage so attribution survives Safari’s cookie expiry and multi-week gaps between first click and signup. There is no separate tracking call — one init() per page load is the whole thing.

Identify

Call when a user signs up or logs in — any time you learn their ID. This is what stitches the authenticated user to the click that brought them in:

await op.identify(currentUser.id);

identify() takes exactly one argument: your internal user ID. Pass the same identifier you’ll later use when reporting events — that’s the join key for the whole attribution chain. If you don’t want to expose raw IDs, a stable hash works too (e.g. sha256(user.id + SALT)), as long as you use the same value everywhere.

Calling identify() repeatedly for the same user is harmless — the same (click, user) pair always maps to one Identity row.

Config

OpenPartner.init({
apiUrl: 'https://app.openpartner.dev/api/t/<your-workspace>',
// Optional:
cookieName: '_cref', // first-party cookie set by the click router
queryParam: 'cref', // query param on landing URLs
storageKey: 'openpartner:cref', // localStorage key
onError: (err) => Sentry.captureException(err),
});

Errors are logged to the console by default — pass onError to hook in observability, or await the identify() call and handle failures yourself.

Framework notes

  • React / Vue / SolidJS — call OpenPartner.init() once at the top of your app; call op.identify() from your auth callback.
  • Next.js App Router — put OpenPartner.init() in a 'use client' provider component mounted in your root layout.
  • SPAs — capture runs on init(), so one init per page load is enough; client-side route changes don’t need re-initialization.