Developer Docs
Everything you need to embed the onboarding checklist in your product and start tracking user activation in minutes.
Quickstart
Three steps to a live checklist. Takes under 5 minutes.
-
1
Get your API key. Sign in to your dashboard, then copy the API key shown in the SDK block at the bottom of the page.
-
2
Drop in the script tag. Paste this into the
<head>of every page where you want to track steps. ReplaceYOUR_API_KEYwith your actual key.
<script src="https://test-co-15-1778663941147-d7db2507.polsia.app/sdk.js?key=YOUR_API_KEY"></script>
-
3
Call
polsia.track()wherever the user completes the action — after a form submit, button click, API response, etc.
// After the user finishes their profile:
polsia.track('profile_complete');
// After they invite a teammate:
polsia.track('invite_teammate');
Full example
Copy-paste this HTML file to see the SDK running end-to-end on a sample page. Replace YOUR_API_KEY with your key from the dashboard.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My App</title>
<!-- 1. Load the SDK with your API key -->
<script src="https://test-co-15-1778663941147-d7db2507.polsia.app/sdk.js?key=YOUR_API_KEY"></script>
</head>
<body>
<h1>Welcome! Let's get you set up.</h1>
<!-- 2. Track steps from button clicks or form submits -->
<button onclick="completeProfile()">Save profile</button>
<button onclick="inviteTeammate()">Invite a teammate</button>
<script>
function completeProfile() {
// Your real logic here — save to DB, etc.
// Then tell Onboard the step happened:
polsia.track('profile_complete');
}
function inviteTeammate() {
polsia.track('invite_teammate');
}
</script>
</body>
</html>
Open your browser console after clicking a button — you'll see [polsia] Step tracked: profile_complete confirming the call succeeded.
API key
Your API key authenticates all SDK and REST API calls. It is scoped to your account — every user who signs up gets their own key.
Where to find it
Go to your dashboard. Scroll to the Embeddable SDK section. Your key is displayed there with a copy button.
How to rotate it
If your key is ever exposed, contact support@polsia.com to issue a new one. After rotation, update the ?key= parameter in your script tag and any server-side calls — the old key becomes invalid immediately.
Step tracking reference
polsia.track(stepKey)
Marks a checklist step as complete for the user identified by your API key. Safe to call multiple times — subsequent calls for an already-complete step are no-ops.
polsia.track('profile_complete');
Valid step keys
| Step key | Type | Description |
|---|---|---|
| confirm_email | string | User confirmed their email address |
| profile_complete | string | User finished setting up their profile. Also stops the T+24h nudge email. |
| invite_teammate | string | User invited at least one teammate. Completing all steps stops the email sequence entirely. |
Response (console)
On success, a log line appears in the browser console:
[polsia] Step tracked: profile_complete { step: { key: "profile_complete", completed_at: "2026-05-13T..." }, progress: { completed: 2, total: 3 } }
Event callbacks
Listen for step completions from other parts of your app using the polsia:tracked custom DOM event:
window.addEventListener('polsia:tracked', function(e) {
var stepKey = e.detail.step_key; // e.g. "profile_complete"
var progress = e.detail.progress; // { completed: 2, total: 3 }
// Example: update your own progress UI
updateMyProgressBar(progress.completed, progress.total);
});
polsia:tracked after every successful server response, so you can sync your own UI without polling.
Configuration options
Pass an options object to polsia.init() after the script tag loads to customise behaviour. All fields are optional — sensible defaults apply.
polsia.init({
// Override the API key baked into the script URL (rarely needed)
apiKey: 'your-api-key',
// Base URL of the Onboard server (default: inferred from script src)
baseUrl: 'https://test-co-15-1778663941147-d7db2507.polsia.app',
// Log level: 'debug' | 'warn' | 'silent' (default: 'warn')
logLevel: 'warn',
// Fired after every successful track call
onTracked: function(stepKey, progress) {
console.log('Tracked:', stepKey, progress);
},
// Fired when a track call fails (network error or invalid key)
onError: function(stepKey, error) {
console.error('Track failed:', stepKey, error);
},
});
Options reference
| Option | Default | Description |
|---|---|---|
| apiKey | from URL | Your API key. Automatically set via ?key= param — only override if loading the script without a query string. |
| baseUrl | auto | Base URL of the Onboard server. Inferred from the src of the script tag at load time. |
| logLevel | 'warn' |
Console verbosity. Set to 'debug' during development to see every request/response. 'silent' disables all output. |
| onTracked | — | Callback fired after each successful track. Receives (stepKey: string, progress: {'{'}completed, total{'}'} ). |
| onError | — | Callback fired when a track call fails. Receives (stepKey: string, error: string). |
Custom CSS hooks
The SDK does not inject any UI — it's purely data. Style your own checklist component however you like, and call polsia.track() to back it with real persistence. The dashboard checklist is a reference implementation you can fork from the codebase.
REST API — server-side tracking
If you'd rather complete steps from your backend (e.g. after a database write), call the REST endpoint directly. No browser SDK needed.
POST /api/sdk/track
Marks a step as complete for the user who owns the given API key.
curl -X POST https://test-co-15-1778663941147-d7db2507.polsia.app/api/sdk/track \
-H "Content-Type: application/json" \
-d '{
"key": "YOUR_API_KEY",
"step_key": "profile_complete"
}'
Request body
| Field | Type | Description |
|---|---|---|
| key | string (required) | Your API key, from the dashboard. |
| step_key | string (required) | One of: confirm_email, profile_complete, invite_teammate. |
Success response 200
{
"success": true,
"step_key": "profile_complete",
"progress": {
"step": {
"id": 42,
"key": "profile_complete",
"title": "Complete your profile",
"completed_at": "2026-05-13T10:00:00.000Z"
}
}
}
Error responses
| Status | Error | Cause |
|---|---|---|
| 400 | key and step_key are required |
Missing a required field in the request body. |
| 400 | step_key must be one of: ... |
Unrecognised step key. |
| 401 | Invalid API key |
Key not found or has been rotated. |
| 500 | Internal error |
Database or server error. Retry with backoff. |
Node.js example
const API_KEY = process.env.ONBOARD_API_KEY;
async function trackStep(stepKey) {
const res = await fetch(
'https://test-co-15-1778663941147-d7db2507.polsia.app/api/sdk/track',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ key: API_KEY, step_key: stepKey }),
}
);
if (!res.ok) throw new Error(`Track failed: ${res.status}`);
return res.json();
}
// Call after your own business logic succeeds:
await trackStep('profile_complete');
Troubleshooting
Nothing happens when I call polsia.track()
Open the browser console. If you see [polsia] No API key configured, the ?key= param is missing from your script tag URL. Make sure the full URL ends with ?key=YOUR_API_KEY.
CORS error in browser console
The SDK endpoint explicitly allows cross-origin requests. If you're seeing a CORS error, check that you're calling /api/sdk/track (not some other path). Verify the baseUrl is correct — an extra trailing slash or wrong subdomain is the usual culprit.
Content Security Policy (CSP) blocking the script
If your app sets a Content-Security-Policy header, add the following to your script-src directive:
Content-Security-Policy: script-src 'self' https://test-co-15-1778663941147-d7db2507.polsia.app;
If you also make fetch calls from client-side JS, add the domain to connect-src too:
Content-Security-Policy: script-src 'self' https://test-co-15-1778663941147-d7db2507.polsia.app; connect-src 'self' https://test-co-15-1778663941147-d7db2507.polsia.app;
401 — Invalid API key
Double-check that you copied the full key from the dashboard with no extra spaces. If the key still fails after pasting cleanly, contact support to check if it was rotated.
Steps complete in the dashboard but emails still send
The email sequence checks profile_complete for the T+24h nudge and requires all steps complete to stop entirely. Confirm the step key you're tracking exactly matches profile_complete (case-sensitive, underscore not hyphen).
polsia.track is not a function
The SDK hasn't loaded yet when your code runs. Either move your <script src="..."> tag higher in the <head>, or wrap your polsia.track() calls in a DOMContentLoaded listener:
document.addEventListener('DOMContentLoaded', function() {
// polsia is guaranteed to exist here
polsia.track('confirm_email');
});
Need help?
Something not working? Question about the API? We're one email away.