SDK Reference/CDN / Script Tag
Framework
@swake/web

CDN / Script Tag

Integration guide for CDN / Script Tag. Uses the @swake/web SDK, which works with any JavaScript framework or vanilla JS.

Overview

The CDN build exposes the exact same @swake/web API as a global Swake object — no bundler or npm install required.

@swake/web/ui (the trigger button, feedback form, history panel, and survey modals) is a separate <script type="module"> import — load it alongside the core script to get the visual widgets.


Getting Started

Script Tag (IIFE)

Load Swake via a script tag with no bundler required. The IIFE bundle exposes a global Swake object.

html
<head>
  <script src="https://cdn.jsdelivr.net/npm/@swake/web/dist/swake.min.global.js"></script>
</head>
<body>
  <script>
    Swake.default.init({ apiKey: 'ep_live_your_api_key' });

    Swake.default.identify({
      userId: 'user_123',
      email: 'user@example.com',
    });

    document.getElementById('feedback-btn').addEventListener('click', () => {
      Swake.default.showFeedbackForm();
    });
  </script>
</body>

The IIFE bundle does not include the UI widgets. For the FAB and widget panels via CDN, add: <script type="module">import '@swake/web/ui';</script>


ESM via CDN

html
<script type="module">
  import Swake from 'https://cdn.jsdelivr.net/npm/@swake/web/dist/index.js';
  import 'https://cdn.jsdelivr.net/npm/@swake/web/dist/ui.js';

  Swake.init({ apiKey: 'ep_live_your_api_key' });
</script>

Identifying Users

javascript
Swake.default.identify({
  userId: 'user_123',
  email: 'jane@example.com',
  name: 'Jane Smith',
});

// On logout
Swake.default.clearIdentity();

Customization

Theme Customization

Pass a theme object in init() to brand all Swake widgets.

html
<script type="module">
  import Swake from 'https://cdn.jsdelivr.net/npm/@swake/web/dist/index.js';
  import 'https://cdn.jsdelivr.net/npm/@swake/web/dist/ui.js';

  Swake.init({
    apiKey: 'ep_live_your_api_key',
    theme: {
      primaryColor: '#8B5CF6',
      backgroundColor: '#FFFFFF',
      textColor: '#0F172A',
      borderRadius: 12,
    },
  });
</script>
TokenDefaultDescription
primaryColor#6366F1Buttons, active states, FAB background
successColor#10B981Success checkmark, resolved badges
dangerColor#EF4444Error borders, destructive actions
backgroundColor#FFFFFFModal / panel background
surfaceColor#F9FAFBInput fields, secondary surfaces
overlayColorrgba(0,0,0,0.45)Backdrop behind modals
textColor#111827Primary text
textSecondary#6B7280Labels, placeholders, metadata
borderColor#E5E7EBInput borders, dividers
borderRadius8Corner radius for inputs and buttons
fontFamilySystem defaultFont family applied to all text

AI Setup

Using Claude Code

Prefer to let an AI coding agent do the wiring? Run Claude Code from the root of your site's repository and paste the prompt below. It reads this page as the source of truth, detects your stack, asks you for your API key and anything else it needs, then wires up @swake/web, init(), identify(), the widgets, and theming — in one shot.

Prerequisites

Before you run the prompt, set up your project in the Swake portal and grab the values the agent will ask for — it only writes placeholders to your env files, so you supply the real values yourself.

  1. Sign in to the Swake portal and create a project (or open an existing one).
  2. In Project settings → API keys, get existing or create a key and copy it — it's shown once and starts with ep_live_.
  3. If you want the voting board, create a board and copy its slug from the board's URL / settings.

Have these ready when the agent prompts you — the same values you'd otherwise wire up by hand:

ValueWhere to find itExample
apiKeyProject settings → API keysep_live_…
baseUrlAPI endpoint — optional, only needed when self-hosting or routing through your own backendhttps://api.swake.io
boardSlugVoting board settings — optional; passed to getBoardItems() / vote(), not init()public-roadmap

The prompt is additive and safe: a Swake or network error must never break your app's boot or existing behavior. The agent pauses and asks before installing packages or writing secrets, and it never guesses APIs that aren't in these docs. Note that a CDN integration necessarily exposes your ep_live_ key in page source, and the browser asserts the user's identity. The prompt states this outright and offers the server-side alternative if that trade-off doesn't suit you.

The prompt

Run Claude Code from your project root and paste this. It targets CDN / Script Tag specifically, and re-reads this guide before it writes anything, so it stays correct as the SDK evolves.

Claude prompt
Fully integrate the Swake feedback SDK (feedback forms, bug reports, surveys/NPS, in-app notifications, voting boards) into this site via the Swake CDN build, with no bundler. Treat it as additive: a Swake or network failure must NEVER break boot or any existing behavior. Never invent or fake an API that is not in the docs.

1. READ THE DOCS FIRST — they are the source of truth for the script URLs, the global shape, init/identify and every option. Fetch with a browser User-Agent (a plain fetch returns 403): curl -sL -A "Mozilla/5.0" "https://swake.io/docs/sdk?framework=cdn". Then find the pages or templates this needs to go into (a shared header, layout, or template partial — not one page at a time) and say which files you intend to edit before editing them.
2. ASK BEFORE DECIDING ANYTHING (AskUserQuestion): (a) the API key (ep_live_...), an optional baseUrl, and a voting-board slug if they want the board; (b) whether they want the IIFE script tag or the ESM build. Then tell them plainly, before writing anything: in this mode the key IS visible to anyone viewing source, and because the browser asserts the user id, a determined visitor could submit as someone else. That is the accepted trade-off of a no-build integration. If either matters, offer the alternative — serve the page from a backend that holds the key, point baseUrl at that backend with credentials: 'include', and have it attach X-API-Key and force the user id from the session.
3. ADD THE SCRIPTS — the IIFE bundle exposes a global and is reached as Swake.default.*, but it does NOT include the visual widgets. To get the trigger FAB, feedback form, history panel and survey modals you must ALSO add the widget module in a separate script type="module". If they chose ESM instead, import both the core and the UI module from the CDN and use the default export directly rather than Swake.default. Put this in ONE shared template so it loads on every page exactly once.
4. INIT EXACTLY ONCE — call init() a single time from that shared template, before any other call. Never repeat it per page or per handler: every method throws "[Swake] SDK not initialized" before init(), and a second init() starts a second offline-queue flush interval without clearing the first. Set trigger: { hidden: true } only if the site will open feedback from its own button.
5. IDENTITY — if the site knows who the visitor is, call identify({ userId, email, name, metadata }) on EVERY page load, not once at login: identity is held in memory only, so each navigation starts fresh. userId must be a stable internal id and every metadata value must be a string. Call clearIdentity() on logout inside a try/catch. If visitors are anonymous, skip identify entirely — feedback still submits, but history, notifications, surveys and voting all need an identified user.
6. POLISH — if the site has a light/dark toggle, call setTheme() from it. Keep the snippet off any page where a survey would be unwelcome (checkout, sign-up), and wire your own buttons to showFeedbackForm() and showFeedbackHistory() where the design calls for it.
7. VERIFY & REPORT — check the browser console for errors on a page that loads the snippet, confirm the trigger appears and that a real submission reaches the Swake dashboard, and confirm the widgets actually render (if they do not, the widget module script is missing — the single most common mistake in this mode). Report which templates you edited, anything left manual, and every assumption you made.

Reference

Full API Reference

Click any method for its full signature, parameters, and an example.

MethodDescription
Initialise the SDK. Must be called once before any other method.
Link the current user. Returns a Promise.
Clear user identity and offline queue.
Replace the global UI theme at runtime.
Submit feedback programmatically (with optional customFields). Returns the created Submission.
Fetch the project's custom field definitions for a custom feedback UI.
List the current user's submissions.
Get full submission detail with comments + attachments.
Edit a submission you own.
Unpublish a submission you own (one-way).
Lightweight submission history (id, title, status, type, createdAt).
Get unread notification count.
List notifications with pagination.
Mark a single notification as read.
Mark all notifications as read.
Open the built-in feedback form widget.
Open the feedback history panel.
Open the feedback form (alias).
Close any open widget (form, history, survey).
Show or hide the trigger FAB.
Fetch voting board items.
Cast a vote on a board item.
Remove a vote from a board item.
Re-check survey eligibility and show the first match.
Show a specific survey (ignores cooldown).
Register survey-shown event listener.
Register survey-completed event listener.
Register survey-dismissed event listener.
Add a custom breadcrumb to the trail.
Return a snapshot of the breadcrumb trail.
Clear the breadcrumb ring buffer.
Register plan-limit event listener.
Tear down all listeners, timers, and UI.