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"
});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. A 202 response means DataCrew accepted the event.
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 revenue event regardless of where the payment originated. Connect Stripe, PayPal, Paddle, Lemon Squeezy, Shopify, WooCommerce, a bank integration, or your own billing system—the only provider-specific work is reading and verifying its webhook.
- 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 customerUse the same opaque
userIdpassed to identify so DataCrew can join revenue to the known visitor. - 4
Make retries idempotentUse the provider’s stable transaction ID and reuse it for every retry. HTTP
202means accepted.
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. Revenue is still recorded when it cannot be attributed.
lifecycleTypeDescribe payment, renewal, trial, subscription, or refund state; add provider when available.
Copy-ready Next.js server helper
Add this helper to your server code, set DATACREW_REVENUE_TOKEN, replace YOUR_SITE_ID, and map the five marked payment values in your verified webhook. The endpoint is POST $https://datacrew.site/api/v1/revenue and successful requests return HTTP 202.
// src/lib/datacrew-revenue.ts
type RevenueEvent = {
transactionId: string;
amount: number;
currency: string;
userId?: 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,
// 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. This preserves the original payment and lets DataCrew subtract the refunded value correctly.
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.
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.