SDK
Installing the SDK
Add the Geyed SDK to your site via npm or CDN, initialize it, and start tours.
Installation
Install the Geyed SDK from npm:
npm install @geyed/sdk
Or load it via CDN if you prefer a script tag. The CDN build is an IIFE bundle that exposes the global Geyed:
<script src="https://unpkg.com/@geyed/sdk/dist/index.iife.js"></script>
Quick start
ESM (npm)
Import init and start in your app's entry point, call init with your API key, then call start to fetch and run the first matching tour:
import { init, start, on } from "@geyed/sdk";
init({
apiKey: "gyd_your_app_key",
baseUrl: "https://api.geyed.com",
debug: true,
});
on("tour_started", (e) => console.log("Tour started:", e.tourName));
await start();
Replace gyd_your_app_key with the API key from your Geyed dashboard. init must be called before start.
IIFE / CDN
<script src="https://unpkg.com/@geyed/sdk/dist/index.iife.js"></script>
<script>
Geyed.init({
apiKey: "gyd_your_app_key",
baseUrl: "https://api.geyed.com",
debug: true,
});
Geyed.start();
</script>
Make sure the IIFE bundle <script> tag appears before your inline script. Use the .iife.js file for CDN usage, not .mjs.
API reference
init(config: GeyedConfig): void
Sets SDK configuration. Must be called before start().
| Field | Type | Description |
|---|---|---|
apiKey | string | Your Geyed app key (required for backend fetch). |
baseUrl | string | Base URL of the Geyed backend (e.g. https://api.geyed.com). |
environment | string? | Optional environment tag forwarded with fetch. |
userId | string? | Optional end-user identifier for analytics and targeting. |
debug | boolean? | Logs SDK activity to the console when true. |
tours | SdkTour[]? | Preload tours inline instead of fetching from the backend. |
import { init } from "@geyed/sdk";
init({
apiKey: "gyd_your_app_key",
baseUrl: "https://api.geyed.com",
userId: "user_123",
debug: true,
});
start(): Promise<void>
Fetches published tours (or uses preloaded or registered tours) and starts the first tour whose urlPattern matches the current window.location.pathname.
await start();
startTour(tourId: number): Promise<void>
Starts a specific tour by ID, bypassing URL matching. Useful for triggering a tour programmatically from a button or onboarding flow.
await startTour(42);
stop(): void
Stops the active tour and removes any overlays and tooltips from the page.
stop();
destroy(): void
Full cleanup: stops any active tour and removes injected styles. Call this when unmounting your application or navigating away in a single-page app.
destroy();
registerTours(tours: SdkTour[]): void
Registers tours locally without making a backend fetch. Useful for offline demos or self-hosted tour definitions.
import { registerTours, start } from "@geyed/sdk";
registerTours([
{
tourId: 1,
tourName: "Welcome Tour",
versionId: 1,
urlPattern: "/dashboard",
triggerType: "auto",
triggerSelector: null,
isRepeatable: false,
themeConfig: null,
transitionPreset: null,
steps: [],
},
]);
await start();
on(event, callback) / off(event, callback)
Subscribe or unsubscribe from SDK lifecycle events. See the Events section below for available event names and payload shapes.
import { on, off } from "@geyed/sdk";
const handler = ({ tourName, stepIndex, stepTitle }) => {
myAnalytics.track("geyed_step_viewed", { tourName, stepIndex, stepTitle });
};
on("step_viewed", handler);
// Later, to unsubscribe:
off("step_viewed", handler);
Defining tours in code
Tours do not have to live in the Geyed dashboard. You can define them directly in your codebase and hand them to the SDK at runtime — no backend fetch required. This is useful for offline demos, self-hosted deployments, and situations where you want tour content to be version-controlled alongside your application code rather than stored in an external service.
There are two ways to supply locally-defined tours: pass them to init() via the tours field, or call registerTours() at any point before start(). Both approaches are equivalent in result — the SDK uses your local definitions instead of fetching from the backend for those tours.
Inline via init
If your tour set is known at boot time, pass it directly to init() via the tours field. The SDK registers every tour in the array immediately during initialization, so by the time you call start() no network request is needed.
import { init, start } from "@geyed/sdk";
init({
apiKey: "gyd_your_app_key",
baseUrl: "https://api.geyed.com",
tours: [
{
tourId: 1,
tourName: "Dashboard Quickstart",
versionId: 1,
urlPattern: "/dashboard",
triggerType: "auto",
triggerSelector: null,
isRepeatable: false,
themeConfig: null,
transitionPreset: null,
steps: [
{
id: 1,
order: 1,
title: "Welcome to your dashboard",
content: "This is where you can see an overview of all your activity at a glance.",
targetSelector: "#dashboard-overview",
placement: "bottom",
transitionPreset: null,
},
],
},
],
});
await start();
After init via registerTours
If you need to supply tours after init() has already been called — for example, once you know which plan the user is on, or after a lazy-loaded module resolves — call registerTours() with your array of tours. You can call it before or after init(), but it must be called before start().
import { init, registerTours, start } from "@geyed/sdk";
init({
apiKey: "gyd_your_app_key",
baseUrl: "https://api.geyed.com",
});
// Called later, e.g. after the user's role is resolved:
registerTours([
{
tourId: 1,
tourName: "Dashboard Quickstart",
versionId: 1,
urlPattern: "/dashboard",
triggerType: "auto",
triggerSelector: null,
isRepeatable: false,
themeConfig: null,
transitionPreset: null,
steps: [
{
id: 1,
order: 1,
title: "Welcome to your dashboard",
content: "This is where you can see an overview of all your activity at a glance.",
targetSelector: "#dashboard-overview",
placement: "bottom",
transitionPreset: null,
},
],
},
]);
await start();
Each call to registerTours() merges the provided tours into the local set, keyed by tourId. Calling it a second time with a tour that shares an existing tourId overwrites that entry; tours with different IDs are unaffected.
Field reference
SdkTour fields
| Field | Type | Required | Notes |
|---|---|---|---|
tourId | number | yes | Any positive integer you pick. Used by analytics events and as a handle for startTour(). |
tourName | string | yes | Display name. Shown in analytics events. |
versionId | number | yes | Version identifier. For code-defined tours, pick any integer (use 1 if you're not versioning locally). |
urlPattern | string | null | yes | Glob pattern matched against window.location.pathname. * is a wildcard. Examples: '/dashboard/*', '/settings', '/users/*/profile'. Use null, '*', or '/*' to match every URL. |
triggerType | 'auto' | 'click' | 'external' | yes | 'auto' starts the tour on the first matching URL visit. 'click' waits for a click on triggerSelector. 'external' means only a manual startTour() call will start it. |
triggerSelector | string | null | yes | CSS selector listened on when triggerType is 'click'. Set to null for 'auto' and 'external'. |
isRepeatable | boolean | yes | If true, the tour can run multiple times for the same user. If false, it runs once per user. |
themeConfig | string | null | yes | JSON-stringified theme config. See below. null uses the default light theme. |
transitionPreset | 'smooth' | 'snappy' | 'fade' | 'slide' | 'none' | null | yes | Tour-level transition animation. null falls back to the default ('smooth'). Individual steps can override this. |
steps | SdkStep[] | yes | Ordered array of steps. |
SdkStep fields
| Field | Type | Required | Notes |
|---|---|---|---|
id | number | yes | Any positive integer unique within the tour. |
order | number | yes | Zero-based or one-based ordering index. Steps render in ascending order. |
title | string | yes | Tooltip heading. |
content | string | yes | Tooltip body text. Supports plain text; rich formatting is applied when tours are authored in the dashboard. |
targetSelector | string | yes | CSS selector pointing at the DOM element the tooltip should attach to. The SDK retries selector resolution briefly before skipping a missing step. |
placement | 'top' | 'bottom' | 'left' | 'right' | yes | Which side of the target element the tooltip renders on. |
transitionPreset | 'smooth' | 'snappy' | 'fade' | 'slide' | 'none' | null | yes | Step-level transition override. null inherits the tour-level preset. |
themeConfig
themeConfig is a JSON-serialized object. The parsed shape is:
{
preset: "light" | "dark" | "blue" | "custom";
primaryColor?: string; // only used when preset is "custom"
backgroundColor?: string; // only used when preset is "custom"
textColor?: string; // only used when preset is "custom"
transitionPreset?: "smooth" | "snappy" | "fade" | "slide" | "none";
}
For a built-in preset, stringify a minimal object:
themeConfig: JSON.stringify({ preset: "dark" }),
For custom colors, set preset: "custom" and supply the color fields:
themeConfig: JSON.stringify({
preset: "custom",
primaryColor: "#2563eb",
backgroundColor: "#0f172a",
textColor: "#f8fafc",
}),
Colors accept any CSS color string (hex, rgb, hsl, named). When a custom field is omitted, the SDK falls back to sensible defaults. If the JSON fails to parse, the SDK falls back to the light preset.
When to use which
Use init({ tours }) for a static set of tours that is always present and known at the time your app boots. Use registerTours() when you need to lazy-load tour definitions — for example after a user logs in and you know their role — or when you want to conditionally register different tours based on runtime application state.
Note: When local tours are registered, the SDK does not make a backend fetch for those tours. You still need to call
start()to begin URL matching and run the first tour whoseurlPatternmatches the current page.
Events
Subscribe to lifecycle events with on and unsubscribe with off.
tour_started
Fires when a tour begins. Payload: { tourId, tourName }.
| Field | Type | Description |
|---|---|---|
tourId | number | Numeric ID of the tour. |
tourName | string | Display name of the tour. |
tour_completed
Fires when a user reaches the final step and advances past it. Payload: { tourId, tourName }.
| Field | Type | Description |
|---|---|---|
tourId | number | Numeric ID of the tour. |
tourName | string | Display name of the tour. |
tour_dismissed
Fires when a user closes a tour before completing it. Payload: { tourId, tourName, stepIndex }.
| Field | Type | Description |
|---|---|---|
tourId | number | Numeric ID of the tour. |
tourName | string | Display name of the tour. |
stepIndex | number | Zero-based index of the step the user was on when they dismissed. |
step_viewed
Fires each time a step becomes visible. Payload: { tourId, tourName, stepIndex, stepTitle }.
| Field | Type | Description |
|---|---|---|
tourId | number | Numeric ID of the tour. |
tourName | string | Display name of the tour. |
stepIndex | number | Zero-based index of the step. |
stepTitle | string | Title of the step. |
import { on } from "@geyed/sdk";
on("step_viewed", ({ tourName, stepIndex, stepTitle }) => {
myAnalytics.track("geyed_step_viewed", { tourName, stepIndex, stepTitle });
});
Browser support
| Browser | Minimum version |
|---|---|
| Chrome / Edge | 90 |
| Firefox | 88 |
| Safari | 15.4 |
The SDK requires fetch, Promise, URLSearchParams, and modern DOM APIs. Internet Explorer is not supported.
Runtime behaviour
When start() is called, the SDK fetches published tours from GET {baseUrl}/api/v1/sdk/tours using your API key. It compares each tour's urlPattern against the current window.location.pathname and runs the first match. For each step, it resolves the targetSelector with retries before skipping a step whose element cannot be found. Once a step is visible it renders an overlay and tooltip with Next, Back, and Close controls and emits the appropriate lifecycle events through the on/off event bus.
Build formats
The npm package ships three output formats in dist/:
| File | Format | Use case |
|---|---|---|
index.mjs | ESM | Bundlers (Vite, webpack, esbuild) |
index.cjs | CommonJS | Node.js or older bundlers |
index.iife.js | IIFE (minified) | Direct <script> tag, exposes window.Geyed |
TypeScript declarations are included as index.d.ts. Source maps are provided for all formats.