Streakfox
SDKs

Web SDK

Install the JavaScript SDK to embed streak mechanics in any web property.

The Web SDK (@streakdev/web) provides a type-safe way to integrate Streakfox into JavaScript and TypeScript applications.

Package status

@streakdev/web is not published to npm yet. Use the dashboard's generated widget snippet for production installs. The examples below document the private-preview package API.

Quick Start

import { createClient, ensureUserHash, getVisitorId } from "@streakdev/web";

// Create a client (do this once)
const client = createClient({
  baseUrl: "https://api.streakfox.com",
});

// Get a stable user identifier
const userHash = ensureUserHash(undefined, currentUser?.id ?? getVisitorId());

// Record an event
await client.recordEvent({
  projectId: "YOUR_PROJECT_ID",
  event: "like",
  userHash,
});

API Reference

createClient(options)

Creates a Streakfox API client.

const client = createClient({
  baseUrl: "https://api.streakfox.com", // API endpoint
  adminToken: "sk_...", // Optional: for server-side aliasUser calls
  aliasToken: "short-lived-signed-token", // Optional: reveals protected browser rewards
  serverIngestToken: "srv_...", // Optional: recommended for server-side /v1/e
});

Options:

  • baseUrl — API endpoint (defaults to production)
  • adminToken — Required for aliasUser() (server-side only)
  • aliasToken — Short-lived project-scoped identity proof used by getState() for protected reward values
  • serverIngestToken — Recommended for server-side recordEvent() calls that do not send an Origin
  • headers — Custom headers to include in requests

client.recordEvent(input)

Records a streak event for a user.

await client.recordEvent({
  projectId: "proj_abc123", // Required: your project ID
  event: "like", // Required: action type
  userHash: "user_hash_here", // Required: user identifier
  meta: { postId: "123" }, // Optional: custom metadata
  idempotencyKey: "unique-id", // Optional: prevent duplicates
});

Input fields:

FieldTypeRequiredDescription
projectIdstringYour project ID from the dashboard
eventstringThe action type (e.g., 'like', 'visit', 'purchase')
kindstringCompatibility alias for event
userHashstringUnique user identifier (use ensureUserHash)
metaobjectCustom metadata attached to the event
idempotencyKeystringPrevents duplicate processing
sessionIdstringGroup events by session

client.getState(input)

Fetches the current widget state for a user.

const state = await client.getState({
  projectId: "proj_abc123",
  userHash: "user_hash_here",
  event: "like",
  identityToken: "short-lived-signed-token", // Or set aliasToken on the client
});

console.log(state.streak.current); // Current streak count
console.log(state.streak.best); // Best streak ever
console.log(state.week); // Last 7 days activity

client.aliasUser(input) (Server-side only)

Links an anonymous visitor to an authenticated user. This merges their streak history.

// Requires adminToken in client options
await client.aliasUser({
  projectId: "proj_abc123",
  anonymousId: "anon_visitor_id",
  userHash: "authenticated_user_hash",
});

⚠️ This requires an adminToken and should only be called from your server, not client-side code.


client.aliasUserWithToken(input)

Links the browser's anonymous visitor to a signed-in user with a short-lived project-scoped token. The client includes the project key in the request URL for project-aware CORS and sends the signed token in the body.

await client.aliasUserWithToken({
  projectId: "proj_abc123",
  token: tokenCreatedOnYourServer,
});

Repeating the same binding is safe. Trying to bind that anonymous visitor to a different user returns 409 ALIAS_IDENTITY_CONFLICT.


Helper Functions

ensureUserHash(knownHash?, fallbackId?)

Selects an existing identifier or a persistent anonymous browser ID. Despite the legacy function name, it does not cryptographically hash a supplied fallback ID. Create signed-in user hashes on your server.

import { ensureUserHash, getVisitorId } from "@streakdev/web";

// For anonymous users
const hash = ensureUserHash(undefined, getVisitorId());

// For authenticated users, supply a pseudonymous hash created on your server
const hash = ensureUserHash(userHashFromServer);

getVisitorId()

Returns a persistent anonymous visitor ID stored in localStorage.

import { getVisitorId } from "@streakdev/web";

const visitorId = getVisitorId(); // e.g., "v_abc123..."

React Integration

Custom Hook Example

import { createClient, ensureUserHash, getVisitorId } from "@streakdev/web";
import { useCallback, useMemo } from "react";

const PROJECT_ID = process.env.NEXT_PUBLIC_STREAK_PROJECT_ID!;

export function useStreak(userId?: string) {
  const client = useMemo(() => createClient({ baseUrl: "https://api.streakfox.com" }), []);

  const userHash = useMemo(() => ensureUserHash(undefined, userId ?? getVisitorId()), [userId]);

  const recordEvent = useCallback(
    (event: string, meta?: Record<string, unknown>) =>
      client.recordEvent({ projectId: PROJECT_ID, event, userHash, meta }),
    [client, userHash],
  );

  const getState = useCallback(
    (event: string) => client.getState({ projectId: PROJECT_ID, event, userHash }),
    [client, userHash],
  );

  return { recordEvent, getState, userHash };
}

Usage

function LikeButton({ postId }: { postId: string }) {
  const { recordEvent } = useStreak(user?.id);

  const handleLike = async () => {
    await likePost(postId);
    await recordEvent("like", { postId });
  };

  return <button onClick={handleLike}>Like</button>;
}

Server-Side Usage (Node.js)

import { createClient } from "@streakdev/web";

const client = createClient({
  baseUrl: "https://api.streakfox.com",
  adminToken: process.env.STREAK_ADMIN_TOKEN, // For aliasUser
});

// Record server-side events
export async function recordPurchase(userId: string, orderId: string) {
  await client.recordEvent({
    projectId: process.env.STREAK_PROJECT_ID!,
    event: "purchase",
    userHash: hashUserId(userId),
    meta: { orderId },
  });
}

// Merge anonymous to authenticated user
export async function onUserLogin(anonymousId: string, userId: string) {
  await client.aliasUser({
    projectId: process.env.STREAK_PROJECT_ID!,
    anonymousId,
    userHash: hashUserId(userId),
  });
}

Next Steps

On this page