Skip to content

Frameworks ​

Every framework uses the same calls. Three rules apply everywhere:

  1. Call init() once, in the browser only, after the app mounts.
  2. In single-page apps, pass trackRouteChanges: true. The SDK then re-runs itself on each client-side navigation, so page targeting stays correct.
  3. Call identify() after sign-in and reset() on sign-out.

Use these options in all examples:

ts
const options = {
  publicKey: "pk_your_workspace_key",
  apiUrl: "https://api.justonecx.qd.je",
  trackRouteChanges: true,
};

INFO

The examples import @justonecx/sdk. If you have not installed it, use the script tag instead.

React, Next.js, Remix, Preact ​

tsx
"use client"; // Next.js App Router only
import { useEffect } from "react";
import { identify, init } from "@justonecx/sdk";

export function JustOneCX({ user }: { user?: { id: string; plan: string } }) {
  useEffect(() => void init(options), []);
  useEffect(() => {
    if (user) void identify(user.id, { plan: user.plan });
  }, [user]);
  return null;
}

Render <JustOneCX user={user} /> once in your root layout.

Vue and Nuxt ​

ts
// Vue: main.ts, after app.mount()
import { init } from "@justonecx/sdk";
void init(options);
ts
// Nuxt: plugins/justonecx.client.ts
// The ".client" suffix keeps it out of server rendering.
import { init } from "@justonecx/sdk";
export default defineNuxtPlugin(() => {
  void init(options);
});

Angular ​

ts
import { isPlatformBrowser } from "@angular/common";
import { Component, PLATFORM_ID, inject } from "@angular/core";
import { init } from "@justonecx/sdk";

@Component({ selector: "app-root", templateUrl: "./app.html" })
export class App {
  constructor() {
    if (isPlatformBrowser(inject(PLATFORM_ID))) void init(options);
  }
}

Svelte and SvelteKit ​

svelte
<script>
  import { onMount } from "svelte";
  import { init } from "@justonecx/sdk";
  onMount(() => void init(options));
</script>

Put this in +layout.svelte (SvelteKit) or App.svelte.

Solid and SolidStart ​

tsx
import { onMount } from "solid-js";
import { init } from "@justonecx/sdk";
onMount(() => void init(options));

Astro, Lit, Alpine, jQuery, plain TypeScript ​

Call init(options) from any client-side script. In Astro, put it in a <script> tag so Astro bundles it for the browser.

Sites without a bundler ​

Plain HTML, WordPress, Webflow and Shopify: use the script tag. Add data-track-route-changes="true" if the site navigates on the client.

Identify after sign-in ​

ts
import { identify, reset } from "@justonecx/sdk";

async function onSignedIn(user: { id: string; plan: string }, userHash: string) {
  await identify(user.id, { plan: user.plan }, { userHash });
}

async function onSignedOut() {
  await reset();
}

userHash comes from your server. See Identity verification.

JustOneCX