creem-datafast-integration
v2.4.1
Published
TypeScript package that connects CREEM payments to DataFast analytics for revenue attribution
Maintainers
Readme
creem-datafast-integration
TypeScript package that automatically connects CREEM payments to DataFast analytics for revenue attribution. Merchants can attribute revenue to traffic sources without writing any glue code.
Features
- Zero glue code — one factory call wires up checkout attribution and webhook forwarding
- Framework adapters — Next.js App Router and Express out of the box, or bring your own
- Production-ready — idempotent webhooks, retries with backoff, HMAC-SHA256 signature verification
- Refund support — forwards
refund.createdasrefunded: truepayment events - Currency-aware — correctly converts zero-decimal (JPY, KRW) and three-decimal (KWD, BHD) currencies
- Session tracking — captures both
datafast_visitor_idanddatafast_session_id - Strict tracking mode — optionally throw errors when visitor ID is missing
- Distributed idempotency — Upstash Redis adapter for serverless/multi-instance deployments
- Configurable — timeout, retry logic, custom logger
- TypeScript first — full type definitions included
Installation
npm install creem-datafast-integrationOptional (for distributed idempotency):
npm install @upstash/redisQuick Start
Next.js
import { NextRequest, NextResponse } from 'next/server';
import { createCreemDataFastClient } from 'creem-datafast-integration';
const creemClient = createCreemDataFastClient({
creemApiKey: process.env.CREEM_API_KEY!,
datafastApiKey: process.env.DATAFAST_API_KEY!,
webhookSecret: process.env.CREEM_WEBHOOK_SECRET,
testMode: true
});
export async function POST(request: NextRequest) {
const { checkoutUrl } = await creemClient.createCheckout(
{ productId: process.env.CREEM_PRODUCT_ID! },
{ request }
);
return NextResponse.redirect(checkoutUrl, { status: 303 });
}import { creemDataFastWebhookHandler } from 'creem-datafast-integration';
export async function POST(request: NextRequest) {
return creemDataFastWebhookHandler(request, {
creemApiKey: process.env.CREEM_API_KEY!,
datafastApiKey: process.env.DATAFAST_API_KEY!,
webhookSecret: process.env.CREEM_WEBHOOK_SECRET,
});
}Express
import express from 'express';
import { createCreemDataFastClient, creemDataFastWebhook } from 'creem-datafast-integration';
const app = express();
const creemClient = createCreemDataFastClient({
creemApiKey: process.env.CREEM_API_KEY!,
datafastApiKey: process.env.DATAFAST_API_KEY!,
webhookSecret: process.env.CREEM_WEBHOOK_SECRET,
});
app.post('/api/checkout', async (req, res) => {
const { checkoutUrl } = await creemClient.createCheckout(
{ productId: process.env.CREEM_PRODUCT_ID! },
{ request: { headers: req.headers, url: req.url } }
);
res.redirect(303, checkoutUrl);
});
app.post(
'/api/webhook/creem',
express.raw({ type: 'application/json' }),
creemDataFastWebhook({
creemApiKey: process.env.CREEM_API_KEY!,
datafastApiKey: process.env.DATAFAST_API_KEY!,
webhookSecret: process.env.CREEM_WEBHOOK_SECRET,
})
);Client-Side
import { getDataFastVisitorIdBrowser, buildCheckoutUrlWithVisitorId } from 'creem-datafast-integration/client';
const visitorId = getDataFastVisitorIdBrowser();
const url = buildCheckoutUrlWithVisitorId('https://checkout.creem.io/xxx', visitorId);Advanced
Strict Tracking Mode
Throw an error when no visitor ID is found at checkout:
const creemClient = createCreemDataFastClient({
creemApiKey: process.env.CREEM_API_KEY!,
datafastApiKey: process.env.DATAFAST_API_KEY!,
strictTracking: true, // throws MissingTrackingError if no visitor ID
});Idempotency (Production)
For multi-instance deployments, use Upstash Redis:
npm install @upstash/redis creem-datafast-integrationimport { Redis } from '@upstash/redis';
import { createCreemDataFastClient, createUpstashIdempotencyStore } from 'creem-datafast-integration';
const redis = new Redis({
url: process.env.UPSTASH_REDIS_REST_URL!,
token: process.env.UPSTASH_REDIS_REST_TOKEN!
});
const creemClient = createCreemDataFastClient({
creemApiKey: process.env.CREEM_API_KEY!,
datafastApiKey: process.env.DATAFAST_API_KEY!,
idempotencyStore: createUpstashIdempotencyStore(redis)
});Configuration Options
{
creemApiKey: string; // CREEM API key
creemWebhookSecret?: string; // For signature verification
datafastApiKey: string; // DataFast API key
testMode?: boolean; // Use test API (default: false)
timeoutMs?: number; // DataFast request timeout (default: 8000)
retry?: {
retries?: number; // Extra attempts (default: 1)
baseDelayMs?: number; // Base backoff (default: 250)
maxDelayMs?: number; // Max backoff (default: 2000)
};
strictTracking?: boolean; // Throw if no visitor ID (default: false)
idempotencyStore?: IdempotencyStore;
logger?: Logger; // Custom logger
}Error Handling
import {
CreemDataFastError,
InvalidCreemSignatureError,
MissingTrackingError,
DataFastRequestError
} from 'creem-datafast-integration';
try {
// ...
} catch (error) {
if (error instanceof InvalidCreemSignatureError) {
// Invalid webhook signature
} else if (error instanceof MissingTrackingError) {
// No visitor ID in strict mode
} else if (error instanceof DataFastRequestError) {
// DataFast API failed
if (error.retryable) {
// Can retry
}
}
}Supported Events
| Event | Description |
|---|---|
| checkout.completed | One-time payment completed |
| subscription.paid | Recurring subscription payment |
| refund.created | Refund issued (forwards as refunded: true) |
Currency Handling
- Standard currencies (USD, EUR, GBP): amounts in cents → decimal (2999 → 29.99)
- Zero-decimal currencies (JPY, KRW, VND): amounts stay as-is
- Three-decimal currencies (KWD, BHD, OMR): amounts divided by 1000
