wakeline
v0.2.0
Published
Wakeline — in-app product guides, checklists, surveys and onboarding for web apps. Re-exports @wakeline/sdk.
Maintainers
Readme
Wakeline
In-app product guides, checklists, surveys and onboarding for web apps. Guides are authored in the Wakeline dashboard; this package renders them.
npm i @wakeline/sdk # or: npm i wakelinewakeline and @wakeline/sdk are the same package published under both names —
install whichever you prefer.
Prefer no build step? The <script> snippet on your dashboard's install page
does the same job and needs no package at all.
Quick start
import { wakeline } from "@wakeline/sdk";
wakeline.init({
key: "wl_pub_…", // publishable key, from Settings → API keys
apiHost: "https://wakeline.io", // your Wakeline origin
});
// Once your user is known. Extra traits become targeting attributes.
wakeline.identify(user.id, { name: user.name, email: user.email, plan: user.plan });apiHost is required here. The <script> snippet infers it from its own
src; an import has no script tag to read, and guessing would point the SDK at
your app's own origin.
Named imports work too, and tree-shake:
import { init, identify, track } from "@wakeline/sdk";Which entry point?
| | @wakeline/sdk | @wakeline/sdk/loader |
|---|---|---|
| SDK code | bundled into your app | fetched from your Wakeline origin |
| Runtime script fetch | none | one |
| Getting SDK updates | you upgrade the package | automatic |
| Added weight | ~35 kB gzipped | ~1 kB |
import { wakeline } from "@wakeline/sdk/loader";
wakeline.init({ key: "wl_pub_…", apiHost: "https://wakeline.io" });The API is identical, so switching is a one-line change.
Use the default where third-party scripts are blocked outright, or when you want the SDK version pinned in your lockfile.
Use /loader to guarantee every visitor runs the current SDK. This matters
more than it sounds: if you build a guide using a step type newer than the
package version your app shipped with, the bundled entry cannot render it until
you upgrade and redeploy. The loader renders it immediately.
Either way your Wakeline origin needs connect-src in your CSP for the API;
/loader additionally needs it in script-src.
API
| Call | What it does |
|---|---|
| init(options) | Start the SDK. Safe to call once; later calls are ignored. |
| identify(externalId, traits?) | Attach a user. Traits become targeting attributes. |
| track(name, properties?) | Fire a custom event; can trigger guides and complete checklist items. |
| page(url?) | Tell the SDK the route changed. Automatic unless autoPage: false. |
| show(flowId) | Show a specific guide on demand. |
| reset() | Clear the identified user, e.g. on logout. |
Calls made before init() are buffered and replayed, so ordering never matters.
Nothing here throws: a fault inside Wakeline must never break your app.
init options
| Option | Type | Default | |
|---|---|---|---|
| key | string | — | Required. Publishable key (wl_pub_…). |
| apiHost | string | — | Required. Your Wakeline origin. |
| autoPage | boolean | true | Watch history/pushState for SPA navigation. |
| lang | string | — | Force a locale; otherwise the identify trait, then navigator.language. |
Server-side rendering
Safe to import anywhere. Next.js, Nuxt, Remix and SvelteKit all evaluate module
scope on the server, so every call no-ops when there is no window rather than
throwing, and runs for real on the client.
"use client";
import { useEffect } from "react";
import { wakeline } from "@wakeline/sdk";
export function Wakeline({ user }: { user: { id: string; email: string } }) {
useEffect(() => {
wakeline.init({ key: process.env.NEXT_PUBLIC_WAKELINE_KEY!, apiHost: "https://wakeline.io" });
wakeline.identify(user.id, { email: user.email });
}, [user.id, user.email]);
return null;
}Strict mode double-invokes effects; init is idempotent, so that is fine.
TypeScript
Types ship with the package — no @types needed. WakelineOptions and
WakelineClient are exported.
Links
MIT
