Web (multi-package)

@sankofa/pulse

Behavior-triggered surveys rendered in-app. Trigger evaluation, custom rendering, and lifecycle event listeners for the web.

@sankofa/pulse runs the survey logic for the Pulse product in the browser. It evaluates triggers, manages eligibility, and exposes a PulseClient that your UI uses to show / dismiss surveys and listen for lifecycle events.

Rendering is your responsibility — the package ships the SurveyRenderer and SurveyState types so you can build a survey UI in React, plain HTML, or any framework. The companion @sankofa/react package ships a <SurveyModal> component that handles the most common case.

Install

bash
npm install @sankofa/pulse

Register the plugin

TypeScript
import { Sankofa } from "@sankofa/browser";
import { pulsePlugin, getPulse } from "@sankofa/pulse";

Sankofa.init({
apiKey: "sk_live_...",
endpoint: "https://api.sankofa.dev",
plugins: [pulsePlugin()],
});

const pulse = getPulse()!;

Show a survey

TypeScript
await pulse.show("srv_post_purchase_feedback");

// Programmatic dismiss
pulse.dismiss();

Listen for lifecycle events

TypeScript
const unsubscribe = pulse.on("completed", (event) => {
console.log("Survey", event.surveyId, "completed");
});

// Lifecycle events: "shown", "completed", "dismissed"

Bundle change events

When the engine publishes a new survey configuration, the SDK refetches eligibility. Listen for those updates:

TypeScript
const unsubscribe = pulse.onBundleChange((bundle) => {
console.log("Pulse bundle updated", bundle.surveys.length, "surveys");
});

Rendering

The package exposes the SurveyRenderer interface and SurveyState type for custom UIs. The simplest path on the web is to use the React companion:

TSX
import { SurveyModal } from "@sankofa/react";

function App() {
return (
  <>
    {/* your app */}
    <SurveyModal />
  </>
);
}

<SurveyModal> consumes the getPulse() client and renders the active survey. Style it via CSS variables that match Sankofa's brand.

Eligibility context

For surveys gated on user-state predicates not visible to the SDK (e.g. internal staff role), set additional context:

TypeScript
pulse.setContext({
tenantId: "acme",
plan: "pro",
userRole: "admin",
});

The next handshake includes this context in the request, so cohort matching can include it.

API summary

SymbolDescription
pulsePlugin(options?)Plugin to register at Sankofa.init.
getPulse()Returns the singleton Pulse client.
pulse.show(surveyId, options?)Show a survey.
pulse.dismiss()Dismiss the active survey.
pulse.on(event, listener)Subscribe to lifecycle events ("shown", "completed", "dismissed").
pulse.onBundleChange(listener)Subscribe to bundle updates.
pulse.setContext(ctx)Set additional eligibility context.
PulseClient (type)The client interface.
SurveyRenderer (type)Interface for custom survey UIs.
SurveyState (type)The active survey state shape.

What's next

Edit this page on GitHub