DataCrew Documentation
Install the tracker, verify your first production signal, and add business events only when they create useful context.
Quick start
Create a website in DataCrew first. The Setup center gives you a unique site ID and a generated snippet. The tracker is always served from the official https://datacrew.site domain.
- 1
Create your websiteEnter the public production domain in DataCrew.
- 2
Choose a platformUse the matching guide below or copy its AI-agent prompt.
- 3
Install onceAdd the snippet to the global head or root layout—not every page.
- 4
Publish and verifyVisit the production site, then run verification in Setup center.
<script>
window.signaldeck = window.signaldeck || function () {
(window.signaldeck.q = window.signaldeck.q || []).push(arguments);
};
</script>
<script defer data-site="YOUR_SITE_ID" src="https://datacrew.site/t.js"></script>Choose your platform
Start with one of the ten most popular integrations below. Every method installs the same tracker; only the global placement and publishing workflow change. If your platform is not listed, use the universal HTML guide.
Next.js App Router
Use next/script in the root layout; supported client-side navigation is captured automatically.
- 1
Open the root App Router layout that wraps every route.
- 2
Import Script from next/script and add the queue and tracker inside <body>.
- 3
Keep the queue beforeInteractive and the tracker afterInteractive.
- 4
Deploy the app, open the production URL, and verify in DataCrew.
import Script from "next/script";
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<Script
id="signaldeck-queue"
strategy="beforeInteractive"
dangerouslySetInnerHTML={{
__html: "window.signaldeck=window.signaldeck||function(){(window.signaldeck.q=window.signaldeck.q||[]).push(arguments)}",
}}
/>
<Script data-site="YOUR_SITE_ID" src="https://datacrew.site/t.js" strategy="afterInteractive" />
{children}
</body>
</html>
);
}JavaScript / TypeScript
Install once, then add explicit events only for meaningful business outcomes.
- 1
Add the universal tracker to the global document or layout.
- 2
Wait until the queue snippet exists before issuing commands.
- 3
Use stable snake_case names for important actions.
- 4
Never send form values, secrets, or arbitrary page text.
<script>
window.signaldeck = window.signaldeck || function () {
(window.signaldeck.q = window.signaldeck.q || []).push(arguments);
};
</script>
<script defer data-site="YOUR_SITE_ID" src="https://datacrew.site/t.js"></script>Shopify
Track storefront journeys first, then connect authoritative revenue server-side.
- 1
Open Online Store → Themes and edit the active theme code.
- 2
Paste the universal snippet immediately before </head> in theme.liquid.
- 3
Save, publish, and visit the live storefront.
- 4
Verify browser tracking before adding the Revenue API.
<script>
window.signaldeck = window.signaldeck || function () {
(window.signaldeck.q = window.signaldeck.q || []).push(arguments);
};
</script>
<script defer data-site="YOUR_SITE_ID" src="https://datacrew.site/t.js"></script>WordPress
Use a trusted header-code plugin or your child theme header.
- 1
Open the site-wide header area in your code injection plugin or child theme.
- 2
Create one enabled header snippet and paste the universal code.
- 3
Publish it across the entire site and clear WordPress/CDN caches.
- 4
Load an uncached public page before verifying.
<script>
window.signaldeck = window.signaldeck || function () {
(window.signaldeck.q = window.signaldeck.q || []).push(arguments);
};
</script>
<script defer data-site="YOUR_SITE_ID" src="https://datacrew.site/t.js"></script>Google Tag Manager
Deploy one Custom HTML tag across the site without editing application files.
- 1
Create a new tag and choose Custom HTML.
- 2
Paste the generated JavaScript and select the All Pages trigger.
- 3
Use Preview to confirm it fires once, then submit and publish the container.
- 4
Visit the public site outside preview mode and verify.
<script>
(function () {
window.signaldeck = window.signaldeck || function () {
(window.signaldeck.q = window.signaldeck.q || []).push(arguments);
};
var tracker = document.createElement("script");
tracker.defer = true;
tracker.setAttribute("data-site", "YOUR_SITE_ID");
tracker.src = "https://datacrew.site/t.js";
document.head.appendChild(tracker);
})();
</script>Webflow
Project-level head code installs the tracker on every published page.
- 1
Open Project Settings rather than an individual page.
- 2
Paste the universal snippet into the Head code field.
- 3
Save and publish to the production domain; Designer preview is not enough.
- 4
Open the published site and verify the signal.
<script>
window.signaldeck = window.signaldeck || function () {
(window.signaldeck.q = window.signaldeck.q || []).push(arguments);
};
</script>
<script defer data-site="YOUR_SITE_ID" src="https://datacrew.site/t.js"></script>React Router
Install once in the shared HTML document for React Router applications.
- 1
Open the index.html file used by the application build.
- 2
Paste the universal snippet once inside <head>.
- 3
Build and deploy the application.
- 4
Open the public site, change routes, and verify the signal.
<script>
window.signaldeck = window.signaldeck || function () {
(window.signaldeck.q = window.signaldeck.q || []).push(arguments);
};
</script>
<script defer data-site="YOUR_SITE_ID" src="https://datacrew.site/t.js"></script>Vue.js
Load the tracker in the main entry file before mounting the Vue application.
- 1
Open src/main.ts or src/main.js.
- 2
Create the queue, append the generated tracker script, then mount the app.
- 3
Replace YOUR_SITE_ID with the ID from Setup center.
- 4
Build, deploy, and verify on the public domain.
// src/main.ts
import { createApp } from "vue";
import App from "./App.vue";
window.signaldeck = window.signaldeck || function (...args) {
(window.signaldeck.q = window.signaldeck.q || []).push(args);
};
const tracker = document.createElement("script");
tracker.defer = true;
tracker.dataset.site = "YOUR_SITE_ID";
tracker.src = "https://datacrew.site/t.js";
document.head.appendChild(tracker);
createApp(App).mount("#app");Wix
Use Wix custom code to add the tracker to every page.
- 1
Open your site dashboard, then Settings → Custom Code.
- 2
Add the universal snippet to Head and select All pages.
- 3
Choose to load it once per page.
- 4
Publish the site, visit the live domain, and verify.
<script>
window.signaldeck = window.signaldeck || function () {
(window.signaldeck.q = window.signaldeck.q || []).push(arguments);
};
</script>
<script defer data-site="YOUR_SITE_ID" src="https://datacrew.site/t.js"></script>Squarespace
Header code injection installs DataCrew across the Squarespace site.
- 1
Open Settings → Advanced → Code Injection.
- 2
Paste the universal snippet into the Header field.
- 3
Save the change.
- 4
Visit the public site outside the editor and verify.
<script>
window.signaldeck = window.signaldeck || function () {
(window.signaldeck.q = window.signaldeck.q || []).push(arguments);
};
</script>
<script defer data-site="YOUR_SITE_ID" src="https://datacrew.site/t.js"></script>HTML / universal
For static HTML and any platform with site-wide head access.
- 1
Open the shared document template or site-wide head settings.
- 2
Paste the snippet once before the closing </head> tag.
- 3
Replace YOUR_SITE_ID with the ID from DataCrew Setup center.
- 4
Publish, visit the public domain, and verify the first signal.
<script>
window.signaldeck = window.signaldeck || function () {
(window.signaldeck.q = window.signaldeck.q || []).push(arguments);
};
</script>
<script defer data-site="YOUR_SITE_ID" src="https://datacrew.site/t.js"></script>Custom events
Page views, sessions, acquisition, scroll milestones, engagement, outbound clicks, supported form submissions, and SPA route changes are automatic. Add explicit events only for meaningful business outcomes.
- Use stable names such as
trial_started. - Keep properties small and useful for filtering.
- Never include form values, tokens, or arbitrary DOM text.
window.signaldeck?.("track", "trial_started", {
plan: "pro",
source: "pricing_page"
});Identify users
Call identify after authentication, when your application has a stable internal customer ID. This connects future activity without browser fingerprinting.
- Prefer an opaque internal ID over an email address.
- Do not identify anonymous landing-page visitors.
- Attach only non-sensitive properties your analytics team needs.
window.signaldeck?.("identify", "customer_123", {
plan: "pro"
});Build an ordered funnel
A funnel answers one precise question: how many of the same visitors completed these actions in this order and within the allowed time? It does not divide unrelated event totals.
Viewed pricingPage · /pricing
Started trialEvent · trial_started
Completed paymentEvent · payment_completed
Create it in DataCrew
- 1
Open Conversions → FunnelsSelect the website whose events and pages should be measured.
- 2
Name the journeyUse a shared business label such as “Trial to paid” and add a sentence describing the outcome.
- 3
Add ordered stepsChoose Page for an exact path such as
/pricing, or Event for a stable event such astrial_started. - 4
Choose the ordering ruleSequential fits most journeys. Strict is useful only when each step must be the next tracked action.
- 5
Set the conversion windowChoose how long a visitor has after Step 1 to complete the outcome.
- 6
Open the analysisReview conversion, drop-off, timing, and the matched visitor journeys behind every number.
Visitors at this step divided by visitors at the previous step.
300 ÷ 600 = 50%Visitors at this step divided by visitors who entered Step 1.
300 ÷ 1,000 = 30%Visitors who reached one step but did not reach the next required step.
600 − 300 = 300Sequential or strict?
Sequential — recommendedpricing → button click → trial_started still converts because the required steps remain in order.
StrictThe button click breaks that attempt because trial_started was not the next tracked action.
How to read an empty funnel
An empty result does not mean the feature is broken. Confirm that Step 1 occurred inside the selected report range, every event name and page path matches exactly, later steps occurred in order, and the visitor completed them before the conversion window expired.
Create your Revenue API token
The token proves that your backend is allowed to write revenue for one DataCrew website.
This follows least privilege. If the token is ever exposed, it can only submit revenue events—it cannot read analytics, identify users, send unrelated events, or change website settings. Use separate tokens for separate server jobs so one secret can be revoked without interrupting everything else.
- 1Select your website
Sign in to DataCrew and choose the production website that should receive revenue.
- 2Open website Settings
Use the website sidebar to open Settings. Tokens belong to one website, so create it in the correct workspace.
- 3Choose Data & access
Open the Data & access tab, then scroll to the API tokens card.
- 4Configure least privilege
Enter a clear name such as “Production revenue.” Leave only Revenue checked so the token receives the revenue:write scope.
- 5Create and copy it now
Click Create scoped token and copy the secret immediately. DataCrew hashes it and will not display the full value again.
- 6Store it on your server
Save it as DATACREW_REVENUE_TOKEN in your hosting provider’s server environment variables, then redeploy. Never use a NEXT_PUBLIC_ or browser-exposed variable.
The secret is shown once. Copy the complete sd_… value when it appears. If it is lost, create a replacement token and revoke the old one.
Optional: send a first request with cURL
Run this only from a secure server terminal after setting the token. Replace the placeholder token, site ID, transaction, amount, currency, and user ID. An HTTP 202 response confirms DataCrew accepted the revenue event and reports whether it was attributed, recorded, refunded, or skipped as a duplicate.
curl -X POST "https://datacrew.site/api/v1/revenue" \
-H "Authorization: Bearer sd_your_revenue_token" \
-H "Content-Type: application/json" \
-d '{
"siteId": "YOUR_SITE_ID",
"transactionId": "txn_123",
"amount": 49,
"currency": "USD",
"userId": "customer_123",
"provider": "stripe",
"lifecycleType": "payment"
}'One Revenue API. Any payment provider.
DataCrew receives one consistent payment event regardless of where the revenue originated. Choose your provider below to jump directly to its complete setup guide.
Metadata and webhook delivery are both required. Checkout metadata preserves the DataCrew visitor/session context; the verified webhook sends the confirmed amount to the Revenue API.
- 1
Create a scoped tokenGenerate a token with only
revenue:writepermission and keep it in a server environment variable. - 2
Choose the trusted triggerSend after your backend or verified provider webhook confirms a payment, renewal, trial change, or refund.
- 3
Match the customerForward
visitorIdandsessionIdfrom checkout metadata, or use the same opaqueuserIdpassed to identify. - 4
Make retries idempotentReuse the provider’s stable
transactionIdfor every retry. The response reports attributed, recorded, refunded, or duplicate.
Request fields that matter
transactionIdA stable, unique payment-event ID. Use a separate stable ID for a refund.
amount + currencyNormal currency units, such as 49 for $49, with a three-letter code like USD.
userIdThe same internal customer ID used by identify. The optional email field provides a fallback identity match.
lifecycleTypeDescribe payment, renewal, trial, subscription, or refund state; add provider when available.
Copy-ready Next.js server helper
Add this helper to server code, set DATACREW_REVENUE_TOKEN, and map the payment values in your verified webhook. The endpoint is POST $https://datacrew.site/api/v1/revenue; include the website’s siteId in every request.
// src/lib/datacrew-revenue.ts
type RevenueEvent = {
transactionId: string;
amount: number;
currency: string;
userId?: string;
visitorId?: string;
sessionId?: string;
provider: string;
lifecycleType?: "payment" | "subscription_renewed" | "refund";
renewal?: boolean;
refunded?: boolean;
};
export async function sendRevenue(event: RevenueEvent) {
const response = await fetch("https://datacrew.site/api/v1/revenue", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.DATACREW_REVENUE_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ siteId: "YOUR_SITE_ID", lifecycleType: "payment", ...event }),
});
if (!response.ok) {
throw new Error(`DataCrew revenue request failed: ${response.status}`);
}
}
// In your verified payment webhook, call:
// await sendRevenue({
// transactionId: providerEvent.id,
// amount: providerEvent.amount,
// currency: providerEvent.currency,
// userId: providerEvent.customerId,
// visitorId: providerEvent.metadata?.datacrew_visitor_id,
// sessionId: providerEvent.metadata?.datacrew_session_id,
// provider: "YOUR_PROVIDER",
// });Payments, renewals, and refunds
Use lifecycleType: "payment" for a completed charge and set renewal: true for recurring renewals. Record a refund as its own event with a new stable event ID, lifecycleType: "refund", and refunded: true.
Keep secrets server-side. Never place a revenue token in client JavaScript, a public environment variable, analytics properties, or logs. Retry temporary failures with the same transaction ID.
Polar
Preserve DataCrew attribution in checkout metadata, then record revenue from a verified Polar order or subscription event.
- 1
Copy the DataCrew visitor and session cookie values into Polar checkout metadata when the checkout is created on your server.
- 2
Verify the Polar webhook signature before reading an order, subscription, renewal, or refund payload.
- 3
Map the provider event's stable ID, amount in normal currency units, currency, customer ID or email, and the DataCrew metadata into the Revenue API request.
- 4
Send provider: polar and the matching lifecycle type. Reuse the same transaction ID for webhook retries and use a separate stable event ID for refunds.
Server-side only. Verify the provider event before sending revenue, keep the DataCrew token secret, and never report money from browser code.
Stripe
Carry visitor and session context through Checkout metadata, then record confirmed money from a verified Stripe webhook.
- 1
Copy the DataCrew visitor and session cookie values into Stripe Checkout Session metadata in your server-side checkout handler.
- 2
Verify the Stripe webhook signature and handle the payment, subscription renewal, or refund event that is authoritative for your integration.
- 3
Map the stable Stripe event or payment ID, amount in normal currency units, currency, customer ID or email, and Checkout metadata into the Revenue API request.
- 4
Send provider: stripe and the matching lifecycle type. Reuse the same transaction ID for retries and give each refund its own stable event ID.
Server-side only. Verify the provider event before sending revenue, keep the DataCrew token secret, and never report money from browser code.
Lemon Squeezy
Forward confirmed order and subscription lifecycle events from your verified Lemon Squeezy webhook.
- 1
Attach the DataCrew visitor, session, or identified user context to the checkout data your backend controls when available.
- 2
Verify the Lemon Squeezy webhook signature before processing order, renewal, subscription, or refund events.
- 3
Map the stable order or webhook event ID, amount in normal currency units, currency, customer ID or email, and available attribution context into the Revenue API request.
- 4
Send provider: lemonsqueezy and the matching lifecycle type. Reuse stable IDs during retries so duplicate webhook deliveries remain idempotent.
Server-side only. Verify the provider event before sending revenue, keep the DataCrew token secret, and never report money from browser code.
Paddle
Forward confirmed transaction and subscription lifecycle events from your verified Paddle webhook.
- 1
Carry the DataCrew visitor, session, or identified user context into the Paddle transaction data your server can recover later.
- 2
Verify the Paddle webhook signature before processing completed transactions, renewals, cancellations, or refunds.
- 3
Map the stable transaction or event ID, amount in normal currency units, currency, customer ID or email, and attribution context into the Revenue API request.
- 4
Send provider: paddle and the matching lifecycle type. Reuse stable IDs for retries and use a distinct stable event ID for each refund.
Server-side only. Verify the provider event before sending revenue, keep the DataCrew token secret, and never report money from browser code.
Custom API
Connect any billing system that can call the DataCrew Revenue API from a trusted server after payment confirmation.
- 1
Create a Revenue-only API token in DataCrew and store it as DATACREW_REVENUE_TOKEN in your server environment.
- 2
Choose the backend job or verified provider webhook that authoritatively confirms payments, renewals, trials, and refunds.
- 3
POST the site ID, stable transaction ID, amount, currency, provider, lifecycle type, and the best available user, visitor, or session identifier to the Revenue API.
- 4
Treat HTTP 202 as accepted. Reuse transaction IDs for retries and use a separate stable event ID with refunded: true for refunds.
Server-side only. Verify the provider event before sending revenue, keep the DataCrew token secret, and never report money from browser code.
Privacy controls
Collected by default
Page path, referrer and campaign context, broad device details, safe events, approximate engagement, and session continuity.
Not collected
Form values, arbitrary URL queries, raw stored IP addresses, session replay, or browser fingerprints.
Your controls
Cookie or cookieless mode, Do Not Track support, excluded path prefixes, allowed domains, and explicit event naming.
Troubleshooting
No request received
Confirm the snippet is in the published global layout and check whether /t.js is blocked by a content-security policy or browser extension.
A different domain appears
Install on the domain configured in DataCrew or update the website domain in Settings.
The script appears twice
Keep one installation method—direct code or Tag Manager—to prevent duplicate page views.
A CMS change is missing
Publish the site and clear platform, plugin, CDN, and browser caches.
Local development is ignored
Deploy and open the configured public domain, then run verification again.