Skip to main content

Installation

npm install cms

Requirements

  • Node.js 18+ (recommended) or any runtime with global fetch
  • TypeScript 5+ (optional, for type safety)

Quick Start

import { CMS } from "cms";

const cms = new CMS({
  apiKey: process.env.CMS_API_KEY!,
  timeout: 10_000,
});

Non-Deferred Lead Tracking

Use non-deferred lead tracking when you can send the clickId at the moment you want to record a lead event.
import { CMS } from "cms";

const cms = new CMS({ apiKey: "sk_live_xxx" });

const response = await cms.trackLead({
  clickId: "id_123",
  eventName: "signup_started",
  customerExternalId: "user_42",
  timestamp: new Date().toISOString(),
  customerName: "John Doe",
  customerEmail: "john@example.com",
  customerAvatar: "https://example.com/avatar.jpg"
});

Lead Payload Fields

  • clickId: string - The unique click identifier
  • eventName: string - Name of the lead event (e.g., “signup_started”, “email_verified”)
  • customerExternalId: string - Your internal customer identifier
  • timestamp?: string - ISO 8601 timestamp (defaults to current time)
  • customerName?: string - Full name of the customer
  • customerEmail?: string - Customer’s email address
  • customerAvatar?: string - URL to customer’s avatar/profile picture

Deferred Lead Tracking

Use deferred mode when you can’t reliably send the clickId at the moment of recording a lead event. This enables two-step lead attribution.

Step 1: Store the clickId Association

import { CMS } from "cms";

const cms = new CMS({ apiKey: "sk_live_xxx" });

// Store the clickId <-> customerExternalId association
await cms.trackLead({
  clickId: "id_123",
  eventName: "signup_started",
  customerExternalId: "user_42",
  mode: "deferred",
});

Step 2: Track Using Only customerExternalId

// Later, track using just customerExternalId (no clickId needed)
await cms.trackLead({
  eventName: "email_verified",
  customerExternalId: "user_42",
});
Key Differences:
  • In deferred mode’s first call, you associate a clickId with a customerExternalId
  • In subsequent calls, you only need the customerExternalId the SDK will use the stored association
  • This is useful for complex user journeys where the click context may be lost

Sale Tracking

Track sales/conversions with detailed transaction information.
import { CMS } from "cms";

const cms = new CMS({ apiKey: "sk_live_xxx" });

await cms.trackSale({
  clickId: "id_123",
  customerExternalId: "user_123",
  eventName: "purchase_completed",
  invoiceId: "inv_987",
  amount: 4999,
  currency: "USD",
  timestamp: new Date().toISOString(),
  customerName: "Jane Smith",
  customerEmail: "jane@example.com",
  customerAvatar: "https://example.com/avatar.jpg"
});

Sale Payload Fields

  • clickId: string - The unique click identifier
  • eventName: string - Name of the sale event (e.g., “purchase_completed”)
  • customerExternalId: string - Your internal customer identifier
  • invoiceId: string - Invoice or transaction identifier
  • amount: number - Amount in cents (e.g., 4999 = $49.99)
  • currency: string - 3-letter currency code (e.g., “USD”, “EUR”, “GBP”)
  • timestamp?: string - ISO 8601 timestamp (defaults to current time)
  • customerName?: string - Customer’s name
  • customerEmail?: string - Customer’s email
  • customerAvatar?: string - URL to customer’s avatar

Configuration

type CMSConfig = {
  apiKey: string;
  baseUrl?: string;
  timeout?: number;
  maxRetries?: number;
  retryDelayMs?: number;
  retryMaxDelayMs?: number;
  retryOnStatuses?: number[];
  retryOnNetworkError?: boolean;
};
Defaults:
  • timeout: 10000
  • maxRetries: 2
  • retryDelayMs: 500
  • retryMaxDelayMs: 10000
  • retryOnStatuses: [429, 500, 502, 503, 504]
  • retryOnNetworkError: true

Per-Request Overrides

await cms.trackLead(
  {
    clickId: "id_123",
    eventName: "signup_started",
    customerExternalId: "user_42",
  },
  {
    timeout: 5000,
    maxRetries: 1,
    retryDelayMs: 300,
  }
);

Error Handling

import { CMS, CMSAPIError } from "cms";

const cms = new CMS({ apiKey: process.env.CMS_API_KEY });

try {
  await cms.trackLead({
    clickId: "id_123",
    eventName: "signup_started",
    customerExternalId: "user_42",
  });
} catch (error) {
  if (error instanceof CMSAPIError) {
    console.error("CMS API error", {
      statusCode: error.statusCode,
      type: error.type,
      message: error.message,
    });
  } else {
    console.error("Unexpected error", error);
  }
}

Documentation

For complete documentation, visit TypeScript SDK Docs