npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

creem-datafast-sdk-connect

v1.0.0

Published

Automatically connect CREEM payments to DataFast analytics

Readme

creem-datafast

Automatically connect CREEM payments to DataFast analytics.

This package wraps the core CREEM TypeScript SDK (creem), auto-captures the datafast_visitor_id cookie on checkout, and forwards payment events to DataFast's Payment API via a webhook handler. Merchants add their DataFast API key — the package handles visitor ID capture and revenue forwarding automatically.


Features

| Feature | Description | |---------|-------------| | Zero-glue attribution | checkout.completed and subscription.paid events are mapped and forwarded to DataFast automatically | | Visitor ID auto-injection | Reads datafast_visitor_id from cookies (server-side or client-side) and injects it into CREEM checkout metadata | | Webhook signature verification | Built-in HMAC-SHA256 verification of the creem-signature header | | Framework adapters | Ready-to-use helpers for Express and Next.js (App Router & Pages Router) | | Generic handler | Framework-agnostic handleWebhook() for Fastify, Hono, Bun, Deno, or any custom server | | Client-side helper | Browser utilities to read the visitor ID cookie and append it to checkout URLs | | TypeScript first | Full type definitions for all APIs, webhook payloads, and configuration |


Installation

npm install creem-datafast
# or
pnpm add creem-datafast
# or
yarn add creem-datafast

Environment Variables

DATAFAST_API_KEY=your_datafast_api_key
CREEM_API_KEY=your_creem_api_key
CREEM_WEBHOOK_SECRET=your_creem_webhook_secret

Quick Start

Next.js App Router

Step 1 — Create a checkout session (app/api/checkout/route.ts)

import { NextResponse } from 'next/server';
import { CreemDataFast } from 'creem-datafast';

const integration = new CreemDataFast({
  datafastApiKey: process.env.DATAFAST_API_KEY!,
  creemApiKey: process.env.CREEM_API_KEY!,
  webhookSecret: process.env.CREEM_WEBHOOK_SECRET,
});

export async function POST(request: Request) {
  const { productId } = await request.json();

  const checkout = await integration.createCheckout({
    productId,
    successUrl: 'https://yoursite.com/success',
    // Auto-reads datafast_visitor_id from the request Cookie header
    cookieHeader: request.headers.get('cookie') ?? '',
  });

  return NextResponse.json({ url: checkout.checkoutUrl });
}

Step 2 — Handle webhooks (app/api/webhooks/creem/route.ts)

import { creemDataFastRouteHandler } from 'creem-datafast/next';

export const POST = creemDataFastRouteHandler({
  datafastApiKey: process.env.DATAFAST_API_KEY!,
  webhookSecret: process.env.CREEM_WEBHOOK_SECRET,

  // Optional: called after DataFast has been notified
  onPaymentAttributed: async (event, payload, response) => {
    console.log('Revenue attributed:', payload.transaction_id);
    // Grant user access, update your database, send a welcome email, etc.
  },
});

Next.js Pages Router

Checkout (pages/api/checkout.ts)

import type { NextApiRequest, NextApiResponse } from 'next';
import { CreemDataFast } from 'creem-datafast';

const integration = new CreemDataFast({
  datafastApiKey: process.env.DATAFAST_API_KEY!,
  creemApiKey: process.env.CREEM_API_KEY!,
});

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  const { productId } = req.body;

  const checkout = await integration.createCheckout({
    productId,
    successUrl: 'https://yoursite.com/success',
    cookieHeader: req.headers.cookie,
  });

  res.json({ url: checkout.checkoutUrl });
}

Webhook (pages/api/webhooks/creem.ts)

import { creemDataFastApiRoute } from 'creem-datafast/next';

export default creemDataFastApiRoute({
  datafastApiKey: process.env.DATAFAST_API_KEY!,
  webhookSecret: process.env.CREEM_WEBHOOK_SECRET,
});

// Required: disable Next.js body parsing so the raw body is available
// for CREEM webhook signature verification.
export const config = {
  api: { bodyParser: false },
};

Express

import express from 'express';
import { creemDataFastWebhook, rawBodyParser } from 'creem-datafast/express';
import { CreemDataFast } from 'creem-datafast';

const app = express();

// Webhook route — mount BEFORE express.json()
app.post(
  '/webhooks/creem',
  rawBodyParser(),                // Captures raw body for signature verification
  creemDataFastWebhook({
    datafastApiKey: process.env.DATAFAST_API_KEY!,
    webhookSecret: process.env.CREEM_WEBHOOK_SECRET,
    onPaymentAttributed: async (event, payload) => {
      console.log('Revenue attributed:', payload.transaction_id);
    },
  })
);

// Other routes use the standard JSON parser
app.use(express.json());

// Checkout endpoint
const integration = new CreemDataFast({
  datafastApiKey: process.env.DATAFAST_API_KEY!,
  creemApiKey: process.env.CREEM_API_KEY!,
});

app.post('/checkout', async (req, res) => {
  const checkout = await integration.createCheckout({
    productId: req.body.productId,
    successUrl: 'https://yoursite.com/success',
    cookieHeader: req.headers.cookie,
  });
  res.json({ url: checkout.checkoutUrl });
});

app.listen(3000);

Generic / Framework-Agnostic Handler

Use handleWebhook() directly with any HTTP framework:

import { CreemDataFast } from 'creem-datafast';

const integration = new CreemDataFast({
  datafastApiKey: process.env.DATAFAST_API_KEY!,
  webhookSecret: process.env.CREEM_WEBHOOK_SECRET,
});

// Hono example
app.post('/webhooks/creem', async (c) => {
  const rawBody = await c.req.text();
  const headers = Object.fromEntries(c.req.raw.headers);

  const result = await integration.handleWebhook({ rawBody, headers });

  if (!result.success && !result.skipped) {
    return c.json({ error: result.error }, 400);
  }
  return c.json({ received: true });
});

Client-Side Checkout URL Approach

If you use CREEM's static payment links directly in the browser, append the visitor ID as a query parameter:

import { appendVisitorIdToUrl, withVisitorId } from 'creem-datafast/client';

// Option A: Append visitor ID to a static CREEM payment link
function CheckoutButton({ productId }: { productId: string }) {
  const handleClick = () => {
    const url = appendVisitorIdToUrl(`https://checkout.creem.io/${productId}`);
    window.location.href = url;
  };
  return <button onClick={handleClick}>Buy Now</button>;
}

// Option B: Include visitor ID in a fetch request to your checkout endpoint
async function createCheckout(productId: string) {
  const body = withVisitorId({ productId, successUrl: '/success' });
  const res = await fetch('/api/checkout', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
  });
  const { url } = await res.json();
  window.location.href = url;
}

How It Works

The integration follows the recommended DataFast attribution flow:

1. Visitor arrives on your site → DataFast tracking script sets the datafast_visitor_id cookie.

2. Visitor initiates checkout → Your server-side checkout endpoint calls integration.createCheckout(), which reads the datafast_visitor_id cookie from the request headers and injects it into the CREEM checkout metadata field.

3. Visitor completes payment → CREEM fires a checkout.completed (or subscription.paid) webhook to your endpoint.

4. Webhook handler processes the event → The handler verifies the CREEM signature, extracts the datafast_visitor_id from the checkout metadata, maps the CREEM order data to the DataFast payment format, and calls POST https://datafa.st/api/v1/payments.

5. DataFast attributes the revenue → The payment appears in your DataFast dashboard with full traffic source attribution.


API Reference

new CreemDataFast(config)

The main integration class.

| Option | Type | Required | Description | |--------|------|----------|-------------| | datafastApiKey | string | Yes | DataFast API key (Bearer token). Get from DataFast Dashboard → Website Settings → API. | | creemApiKey | string | No* | CREEM API key. *Required for createCheckout(). | | webhookSecret | string | No | CREEM webhook secret for signature verification. Highly recommended. | | creemServerIdx | 0 \| 1 | No | 0 = production (default), 1 = test/sandbox. | | datafastBaseUrl | string | No | Override the DataFast API base URL (useful for testing). |

integration.createCheckout(options)

Creates a CREEM checkout session with the DataFast visitor ID automatically injected into metadata.

| Option | Type | Description | |--------|------|-------------| | productId | string | CREEM product ID (required). | | cookieHeader | string | Raw Cookie header from the incoming request. Used to auto-extract datafast_visitor_id. | | datafastVisitorId | string | Explicitly provide the visitor ID (overrides cookie extraction). | | successUrl | string | URL to redirect the customer after payment. | | metadata | object | Additional metadata key-value pairs. | | customer | object | Pre-fill customer email and name. | | requestId | string | Optional reference ID for tracking. |

Returns { id, checkoutUrl, datafastVisitorId?, raw }.

integration.handleWebhook(request, options?)

Framework-agnostic webhook handler.

const result = await integration.handleWebhook({
  rawBody: '{"eventType":"checkout.completed",...}',
  headers: { 'creem-signature': 'abc123...' },
});

Options callbacks:

| Callback | Signature | Description | |----------|-----------|-------------| | onPaymentAttributed | (event, payload, response) => void | Called after DataFast is successfully notified. | | onEventSkipped | (event) => void | Called for non-revenue events. | | onError | (error, event?) => void | Called when an error occurs. |

creemDataFastRouteHandler(options) (Next.js App Router)

Returns an async function compatible with export const POST = ....

creemDataFastApiRoute(options) (Next.js Pages Router)

Returns a Next.js API route handler. Remember to export config = { api: { bodyParser: false } }.

creemDataFastWebhook(options) (Express)

Returns an Express RequestHandler. Use rawBodyParser() before it.

Client-Side Helpers (creem-datafast/client)

| Function | Description | |----------|-------------| | getDataFastVisitorId() | Reads datafast_visitor_id from document.cookie. Returns string \| null. | | appendVisitorIdToUrl(url, options?) | Appends ?datafast_visitor_id=... to a URL. | | ensureVisitorIdInUrl(url, options?) | Idempotent version of appendVisitorIdToUrl. | | withVisitorId(body) | Merges datafastVisitorId into a fetch request body object. |


Webhook Events

The following CREEM events are handled:

| Event | Action | |-------|--------| | checkout.completed | Maps order amount/currency/transaction ID + visitor ID → DataFast payment (one-time) | | subscription.paid | Maps last transaction amount/currency/ID + visitor ID → DataFast payment (renewal) | | All other events | Skipped silently; onEventSkipped callback is invoked if provided |


Security

Webhook signature verification is enabled automatically when webhookSecret is provided. The handler computes HMAC-SHA256(rawBody, secret) and compares it to the creem-signature header using a constant-time comparison to prevent timing attacks.

It is strongly recommended to set CREEM_WEBHOOK_SECRET in production. Without it, any HTTP request to your webhook endpoint will be accepted.


License

MIT