# EngageTrack Documentation > EngageTrack is a privacy-first web analytics platform with revenue attribution, funnels, goals, and a full REST API. --- URL: https://engagetrack.net/docs/getting-started.md --- title: Getting Started description: Set up EngageTrack analytics on your website in minutes. Here's how to get started in 4 steps. order: 1 --- # Grow your business with EngageTrack in 4 steps Set up EngageTrack analytics on your website in minutes to find your best marketing channels and grow your business. Here's how to get started in 4 steps: ## 1/ Install tracking script Create a new website and add the tracking script to the `` section of your website: ```html ``` Need to customize the script? Check the [script configuration reference](/docs/advanced/script-configuration) for all available options like localhost tracking, cross-domain setup, custom API endpoints, and more. ### Installation tutorials ## 2/ Connect a payment provider Link your Stripe, LemonSqueezy, Paddle, or Polar account to automatically track revenue and attribute it to your marketing channels. → [Connect payment providers](/docs/revenue-attribution/overview) ## 3/ Set up custom events Track conversions, button clicks, and form submissions with custom goals: ```html ``` ```js // Track a custom goal via HTML attribute // // Or track programmatically window.engagetrack("signup_click", { method: "google" }); // Track revenue window.engagetrack.trackPurchase("order_123", 29.99, "USD"); ``` → [Track custom goals](/docs/tracking/goals) → [Track custom events](/docs/tracking/custom-events) ## 4/ Invite your team Collaborate with your team by inviting members to your organization dashboard. → [Invite team members](/docs/team/invitations) ## Next steps - [Filter your data](/docs/analytics/filtering) to segment visitors - [Set up conversion funnels](/docs/tracking/funnels) - [Configure revenue tracking](/docs/tracking/revenue) - [Explore the API](/docs/api/authentication) --- URL: https://engagetrack.net/docs/custom-domain.md --- title: Custom Domain description: Proxy the EngageTrack script through your own domain to bypass ad blockers and maximize tracking accuracy. order: 2 --- # Custom Domain Some ad blockers block third-party analytics scripts by matching known CDN hostnames like `cdn.engagetrack.net`. Proxying the EngageTrack script through your own domain makes it a first-party resource — ad blockers typically allow first-party traffic. Custom domain proxying is available on the **Agency plan** only. Upgrade at **Settings → Billing** to access this feature. Proxying through a custom domain can improve data accuracy by 10–20% depending on your audience's ad blocker usage rate. ## How It Works Without a proxy, your visitors load the script directly from EngageTrack's CDN: ``` https://cdn.engagetrack.net/sdk.js ``` With a custom domain proxy, the script loads from your own subdomain: ``` https://analytics.yourdomain.com/js/sdk.js ``` Your server or CDN forwards those requests to EngageTrack's origin. From the browser's perspective, all traffic stays on your domain — so ad blockers have no hostname to block. ## Setup Options Choose the approach that matches your infrastructure. ### Nginx Reverse Proxy Add a `location` block to your Nginx configuration: ```nginx location /js/ { proxy_pass https://cdn.engagetrack.net/; proxy_set_header Host cdn.engagetrack.net; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_buffering on; } location /api/event { proxy_pass https://api.engagetrack.net/event; proxy_set_header Host api.engagetrack.net; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } ``` Reload Nginx after saving: `nginx -s reload`. ### Cloudflare Workers Deploy a Worker that forwards requests to EngageTrack's origin: ```js addEventListener("fetch", (event) => { event.respondWith(handleRequest(event.request)); }); async function handleRequest(request) { const url = new URL(request.url); if (url.pathname.startsWith("/js/")) { const origin = "https://cdn.engagetrack.net" + url.pathname.replace("/js", ""); return fetch(origin, request); } if (url.pathname === "/api/event") { return fetch("https://api.engagetrack.net/event", request); } return new Response("Not found", { status: 404 }); } ``` Deploy via the Cloudflare dashboard or `wrangler publish`. ### Vercel Rewrites Add a `rewrites` entry to your `vercel.json`: ```json { "rewrites": [ { "source": "/proxy/sdk.js", "destination": "https://cdn.engagetrack.net/sdk.js" }, { "source": "/proxy/event", "destination": "https://api.engagetrack.net/event" } ] } ``` ### Netlify Redirects Add proxy rules to your `_redirects` file: ``` /proxy/sdk.js https://cdn.engagetrack.net/sdk.js 200! /proxy/event https://api.engagetrack.net/event 200! ``` The `200!` status tells Netlify to proxy the request rather than issue a redirect. ## Update Your Tracking Script Once your proxy is live, point the tracking script at your custom domain using the `data-api` attribute: ```html ``` Replace `YOUR_SITE_PUBLIC_ID` with your actual site ID from the EngageTrack dashboard, and replace `analytics.yourdomain.com` with your actual proxy subdomain. ## Verify It Works 1. Open your browser's DevTools and switch to the **Network** tab. 2. Reload the page. 3. Confirm that `sdk.js` is loaded from your custom domain — not from `cdn.engagetrack.net`. 4. Perform an action that triggers an event (e.g., navigate to another page) and confirm the event request goes to `analytics.yourdomain.com/api/event`. Add `data-debug="true"` to the script tag to enable console logging. This shows you exactly which endpoint each event is sent to, which is useful for verifying your proxy setup. ## Trade-offs Proxying adds a network hop between your server and EngageTrack's API. For most setups this is negligible, but keep in mind: - **Latency:** Requests pass through your infrastructure before reaching EngageTrack. Use a geographically distributed edge (Cloudflare Workers, Vercel Edge) to minimise added latency. - **Bandwidth:** Your proxy handles script and event traffic. At high volumes this may count against your hosting bandwidth quota. - **Maintenance:** If EngageTrack changes its CDN or API endpoints, you will need to update your proxy configuration. ## Next Steps - Return to [Getting Started](/docs/getting-started) for the full list of `data-*` configuration attributes including `data-api`. - See the Configuration Options table in Getting Started for all supported script attributes. --- URL: https://engagetrack.net/docs/installation/overview.md --- title: Installation Guides description: Add EngageTrack analytics to any website or app in under 2 minutes with our lightweight tracking script. order: 1 --- # Installation Guides EngageTrack ships as a single **~3 KB** JavaScript snippet that tracks pageviews, outbound links, file downloads, form submissions, scroll depth, and more — with zero device storage by default. No cookies, no `localStorage`, no consent banner needed. Fully GDPR and ePrivacy compliant out of the box. ## Quick Install Add the script to the `` of any HTML page: ```html ``` That's it. Pageviews are tracked automatically as soon as the script loads. Find your **Site ID** in the EngageTrack dashboard under **Site Settings → General**. ## Framework Guides Choose your stack for a step-by-step walkthrough: | Framework | Guide | | --------- | ----- | | **Next.js** | [Install in Next.js (App Router)](/docs/installation/nextjs) | | **React** | [Install in React (Vite, CRA, etc.)](/docs/installation/react) | | **Vue.js** | [Install in Vue.js](/docs/installation/vuejs) | | **Astro** | [Install in Astro](/docs/installation/astro) | | **WordPress** | [Install on WordPress](/docs/installation/wordpress) | | **Google Tag Manager** | [Install via GTM](/docs/installation/google-tag-manager) | ## What Gets Tracked Automatically Once installed, the SDK automatically captures: - **Pageviews** — every page load and client-side navigation - **Outbound links** — clicks to external domains - **File downloads** — common file extensions (pdf, zip, dmg, etc.) - **Form submissions** — all `
` submit events - **Phone clicks** — `tel:` link clicks - **Scroll depth** — continuous percentage (0-100%) sent with page events - **Time on page** — duration before the visitor leaves Each auto-tracked feature can be toggled on or off per site in **Site Settings → Tracking**. ## Next Steps - [Track custom goals and events](/docs/tracking/goals) - [Set up revenue tracking](/docs/tracking/revenue) - [Configure the script](/docs/advanced/script-configuration) (custom API endpoint, cross-domain, debug mode) --- URL: https://engagetrack.net/docs/installation/nextjs.md --- title: Next.js description: Install EngageTrack in your Next.js application using the App Router. order: 2 --- # Next.js Add EngageTrack analytics to your Next.js application in a few minutes. This guide covers the App Router (Next.js 13+). The SDK handles client-side navigation automatically — no extra configuration needed. ## 1. Add the Script to Your Root Layout Open `app/layout.tsx` and add the EngageTrack script using the Next.js `Script` component: ```tsx import Script from "next/script"; export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( {children}
``` Replace `YOUR_SITE_ID` with the Site ID from your EngageTrack dashboard (**Site Settings → General**). ## 2. React Router Support The EngageTrack SDK automatically detects client-side navigations by listening to `pushState` and `replaceState` calls on the History API. This means **React Router v6+** works out of the box — every route change triggers a pageview. ### Hash Routing If you use `HashRouter`, add `data-hash="true"` to the script tag so hash changes are tracked as pageviews: ```html ``` ## 3. Track Goals in Components Call `window.engagetrack()` from any event handler: ```tsx function PricingCard({ plan }: { plan: string }) { const handleSelect = () => { window.engagetrack("plan-selected", { plan }); }; return (

{plan}

); } ``` ### Track on Mount Use `useEffect` to fire an event when a component mounts (e.g., when a user reaches a specific page): ```tsx import { useEffect } from "react"; function ThankYouPage() { useEffect(() => { window.engagetrack("conversion-complete"); }, []); return

Thank you for your purchase!

; } ``` Always wrap `window.engagetrack` calls in `useEffect` or event handlers. Never call it at the top level of a component — it will run during SSR/pre-rendering if you use frameworks like Remix or Next.js. ## 4. Track Revenue Use `trackPurchase` for revenue events: ```tsx function CheckoutButton({ amount }: { amount: number }) { const handleCheckout = async () => { await processPayment(); window.engagetrack.trackPurchase("order_123", amount, "USD"); }; return ; } ``` ## 5. Environment Variables (Vite) To avoid hardcoding the Site ID, use Vite environment variables. Create a `.env` file: ```bash VITE_ENGAGETRACK_SITE_ID=your-site-id-here ``` Then reference it in `index.html` using Vite's HTML env replacement: ```html ``` For Create React App, use `REACT_APP_ENGAGETRACK_SITE_ID` and `%REACT_APP_ENGAGETRACK_SITE_ID%` instead. ## Verify Installation 1. Start your dev server (`npm run dev` or `npm start`). 2. Open the app and click through a few pages. 3. In the EngageTrack dashboard, go to the **Realtime** tab — your visits should appear within seconds. If you see your pageviews in Realtime, you're all set. If not, add `data-debug="true"` to the script tag and check the browser console for diagnostic messages. --- URL: https://engagetrack.net/docs/installation/vuejs.md --- title: Vue.js description: Install EngageTrack in your Vue.js application. order: 4 --- # Vue.js Add EngageTrack to your Vue.js application. This works with both Vue 3 (Vite) and Vue 2 (Vue CLI) projects. ## Option A: Add to index.html (Recommended) The simplest approach is to add the script to your `index.html`. For Vite projects, this file is in the project root. For Vue CLI projects, it's in `public/index.html`. ```html My Vue App
``` Replace `YOUR_SITE_ID` with the Site ID from your EngageTrack dashboard (**Site Settings → General**). ## Option B: Load in App.vue If you prefer to keep everything in Vue, load the script programmatically in your root component: ```vue ``` The `index.html` approach (Option A) is preferred because the script loads earlier and won't miss the initial pageview. Use Option B only if you don't have access to `index.html` or need conditional loading. ## Vue Router Integration The EngageTrack SDK automatically tracks client-side navigations by listening to the History API. If you use Vue Router in `history` mode, every route change is tracked as a pageview with no extra setup. ### Hash Mode If your Vue Router uses `createWebHashHistory`, add `data-hash="true"` to the script tag: ```html ``` ## Track Goals in Components Call `window.engagetrack()` from methods or event handlers: ```vue ``` ### Track on Route Enter Use the `onMounted` hook or a route guard to fire events when users reach specific pages: ```vue ``` Or with a global navigation guard in your router: ```ts // router/index.ts router.afterEach((to) => { if (to.name === "checkout-success") { window.engagetrack("checkout-complete"); } }); ``` ## Track Revenue ```vue ``` ## Verify Installation 1. Start your dev server (`npm run dev`). 2. Navigate between a few pages in your app. 3. In the EngageTrack dashboard, go to the **Realtime** tab — your visits should appear within seconds. If you see your pageviews in Realtime, you're all set. If not, add `data-debug="true"` to the script tag and check the browser console for diagnostic messages. --- URL: https://engagetrack.net/docs/installation/astro.md --- title: Astro description: Install EngageTrack in your Astro website. order: 5 --- # Astro Add EngageTrack analytics to your Astro site. Astro's partial hydration and multi-page architecture make it a great fit for lightweight analytics. ## 1. Add to Your Base Layout Open your base layout file (typically `src/layouts/Layout.astro`) and add the script inside the `` tag: ```astro --- // src/layouts/Layout.astro interface Props { title: string; } const { title } = Astro.props; --- {title} ``` The `is:inline` directive is required. Without it, Astro will try to bundle the script, which breaks the external SDK loading. `is:inline` tells Astro to leave the script tag as-is in the HTML output. ## 2. Environment Variables Use Astro's built-in environment variable support to avoid hardcoding the Site ID. Add to your `.env` file: ```bash PUBLIC_ENGAGETRACK_SITE_ID=your-site-id-here ``` Then reference it in your layout: ```astro ``` Astro environment variables must be prefixed with `PUBLIC_` to be available in client-side code and templates. ## 3. View Transitions Support If you use Astro's View Transitions (``), the EngageTrack SDK handles this automatically. It listens to the History API, so view transition navigations are tracked as pageviews without any extra configuration. ```astro --- import { ViewTransitions } from "astro:transitions"; --- ``` ## 4. Track Goals For static pages, use the `data-goal` HTML attribute: ```astro View Pricing ``` For interactive components (React, Vue, Svelte islands), use the JavaScript API: ```tsx // src/components/SignupForm.tsx (React island) export default function SignupForm() { const handleSubmit = () => { window.engagetrack("signup-completed"); }; return ( ); } ``` ## 5. Astro with SSR If you're running Astro in SSR mode (with an adapter like `@astrojs/node` or `@astrojs/vercel`), the script tag in your layout works the same way. The `is:inline` directive ensures it renders as plain HTML regardless of rendering mode. For server-side event tracking, you can read the visitor cookies in your API routes: ```ts // src/pages/api/convert.ts import type { APIRoute } from "astro"; export const POST: APIRoute = async ({ cookies }) => { const visitorId = cookies.get("engagetrack_visitor_id")?.value; const sessionId = cookies.get("engagetrack_session_id")?.value; await fetch("https://api.engagetrack.net/api/v1/event", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ site_id: import.meta.env.PUBLIC_ENGAGETRACK_SITE_ID, name: "server-conversion", visitor_id: visitorId, session_id: sessionId, }), }); return new Response(JSON.stringify({ ok: true }), { status: 200 }); }; ``` ## Verify Installation 1. Run `npm run dev` to start the Astro dev server. 2. Open your site and navigate between a few pages. 3. In the EngageTrack dashboard, go to the **Realtime** tab — your visits should appear within seconds. If you see your pageviews in Realtime, you're all set. If not, add `data-debug="true"` to the script tag and check the browser console for diagnostic messages. --- URL: https://engagetrack.net/docs/installation/wordpress.md --- title: WordPress description: Install EngageTrack on your WordPress website. order: 6 --- # WordPress Add EngageTrack analytics to your WordPress site. No plugin required — just a single script tag added to your site's header. ## Option A: Insert Headers and Footers Plugin (Easiest) If you're not comfortable editing theme files, use a plugin to inject the script. 1. Install and activate the **WPCode** plugin (formerly Insert Headers and Footers) from the WordPress plugin directory. 2. Go to **Code Snippets → Header & Footer** in the WordPress admin. 3. Paste the following into the **Header** section: ```html ``` 4. Click **Save Changes**. Replace `YOUR_SITE_ID` with the Site ID from your EngageTrack dashboard (**Site Settings → General**). ## Option B: Edit header.php If you prefer not to install a plugin, add the script directly to your theme's header file. 1. In the WordPress admin, go to **Appearance → Theme File Editor**. 2. Select your active theme and open `header.php`. 3. Find the closing `` tag and add the script just above it: ```php ``` 4. Click **Update File**. Editing `header.php` directly means your changes will be lost when the theme updates. To avoid this, use a **child theme** or use the plugin approach (Option A) instead. ## Option C: wp_enqueue_script in functions.php For developers who prefer the WordPress way, add the script via `functions.php`: ```php // functions.php (in your child theme) function engagetrack_enqueue_script() { wp_enqueue_script( 'engagetrack', 'https://cdn.engagetrack.net/sdk.js', array(), null, false // Load in header ); // Add the data-site-id attribute wp_script_add_data('engagetrack', 'data-site-id', 'YOUR_SITE_ID'); } add_action('wp_enqueue_scripts', 'engagetrack_enqueue_script'); // Add defer and data attributes to the script tag function engagetrack_script_attributes($tag, $handle) { if ('engagetrack' !== $handle) { return $tag; } return str_replace( ' src=', ' defer data-site-id="YOUR_SITE_ID" src=', $tag ); } add_filter('script_loader_tag', 'engagetrack_script_attributes', 10, 2); ``` ## Track Goals with HTML Attributes You can track button clicks and link interactions across your WordPress site using `data-goal` attributes. This works in the WordPress block editor, page builders, and raw HTML: ```html View Pricing ``` Most page builders (Elementor, Divi, Beaver Builder) let you add custom HTML attributes to elements. Look for an "Advanced" or "Attributes" section in the element settings. ## WooCommerce Revenue Tracking For WooCommerce stores, add a conversion tracking snippet to the order confirmation page. Add this to your child theme's `functions.php`: ```php function engagetrack_woocommerce_tracking($order_id) { $order = wc_get_order($order_id); if (!$order) return; ?> If you see your pageviews in Realtime, you're all set. If not, add `data-debug="true"` to the script tag and check the browser console for diagnostic messages. --- URL: https://engagetrack.net/docs/installation/google-tag-manager.md --- title: Google Tag Manager description: Install EngageTrack via Google Tag Manager. order: 7 --- # Google Tag Manager If your site already uses Google Tag Manager (GTM), you can deploy EngageTrack without touching your site's source code. ## 1. Create a Custom HTML Tag 1. Open your GTM container and go to **Tags → New**. 2. Name the tag **EngageTrack Analytics**. 3. Click **Tag Configuration** and select **Custom HTML**. 4. Paste the following code: ```html ``` Replace `YOUR_SITE_ID` with the Site ID from your EngageTrack dashboard (**Site Settings → General**). We create the script dynamically instead of using a static `<script>` tag because GTM injects Custom HTML tags into the body. The dynamic approach ensures the script loads with the correct attributes and avoids duplicate loading. ## 2. Set the Trigger 1. Click **Triggering** and select **All Pages**. 2. This fires the tag on every page load, including both the initial load and subsequent navigations. ## 3. Save and Publish 1. Click **Save** on the tag. 2. Use GTM's **Preview** mode to verify the tag fires correctly. 3. Once verified, click **Submit** to publish the container. ## Goal Tracking via GTM DataLayer You can fire EngageTrack goals based on GTM dataLayer events. For example, if your site pushes events to the dataLayer: ```javascript // Your application code dataLayer.push({ event: "form_submitted", formName: "contact", }); ``` Create a second Custom HTML tag in GTM to forward these events to EngageTrack: ### Step 1: Create a DataLayer Variable 1. Go to **Variables → User-Defined Variables → New**. 2. Choose **Data Layer Variable**. 3. Set the variable name to `formName`. 4. Name it **DLV - formName** and save. ### Step 2: Create the Forwarding Tag 1. Create a new **Custom HTML** tag named **EngageTrack - Form Goal**. 2. Paste: ```html ``` 3. Set the trigger to a **Custom Event** with event name `form_submitted`. 4. Save and publish. ## Track Revenue via DataLayer If your e-commerce platform pushes purchase data to the dataLayer: ```javascript dataLayer.push({ event: "purchase", transactionTotal: 99.99, transactionCurrency: "USD", }); ``` Create a Custom HTML tag to forward revenue: ```html ``` Set the trigger to a **Custom Event** with event name `purchase`. Create DataLayer Variables for `transactionTotal` and `transactionCurrency` the same way as described in Step 1 above. ## Verify Installation 1. Open GTM **Preview** mode and load your website. 2. Confirm the **EngageTrack Analytics** tag fires on "Container Loaded". 3. Navigate between a few pages. 4. In the EngageTrack dashboard, go to the **Realtime** tab — your visits should appear within seconds. If you see your pageviews in Realtime, you're all set. If not, add `s.dataset.debug = "true"` to the script creation code (before `document.head.appendChild`) and check the browser console. --- URL: https://engagetrack.net/docs/tracking/goals.md --- title: Goal Tracking description: Track custom conversions and events with EngageTrack's goal system. order: 1 --- # Goal Tracking Goals let you track specific user actions — signups, purchases, button clicks, or any custom event that matters to your business. ## HTML Data Attributes The simplest way to track goals is with `data-goal` attributes on any HTML element: ```html View Pricing ``` When a user clicks the element, EngageTrack automatically fires a goal event. ## JavaScript API ### Plain JavaScript Call `window.engagetrack()` directly or use the `.track()` alias: ```javascript // Simple goal window.engagetrack("newsletter-subscribe"); // Goal with custom properties window.engagetrack("purchase", { plan: "startup", interval: "yearly", amount: "29.99", }); // Alternative .track() alias window.engagetrack.track("newsletter-subscribe"); ``` ### TypeScript / Next.js Because the SDK is loaded via a ` ``` Or if you prefer a single link with manual construction: ```javascript const visitorId = window.engagetrack?.getVisitorId() || ""; const sessionId = window.engagetrack?.getSessionId() || ""; const paymentLink = `https://buy.stripe.com/aBC123dEfGhI?client_reference_id=${visitorId}&engagetrack_session_id=${sessionId}`; window.location.href = paymentLink; ``` Although `client_reference_id` is passed through to the checkout session by Stripe, EngageTrack does **not** currently read this field for attribution. The snippet below is provided for reference, but it will not result in attributed revenue. Use the [Stripe Checkout API](/docs/revenue-attribution/stripe-checkout) for full attribution. ## Step 3: Set Up the Webhook Follow the same webhook setup as [Stripe Checkout](/docs/revenue-attribution/stripe-checkout#step-2-set-up-the-webhook-in-stripe): 1. Go to [Stripe Dashboard → Developers → Webhooks](https://dashboard.stripe.com/webhooks) 2. Click **Add endpoint** 3. Enter the webhook URL: ``` https://api.engagetrack.net/api/v1/webhooks/revenue/stripe/{YOUR_SITE_PUBLIC_ID} ``` 4. Select `checkout.session.completed` and `charge.refunded` events 5. Click **Add endpoint** ## Limitations Payment Links have some limitations compared to the [Checkout Sessions API](/docs/revenue-attribution/stripe-checkout): | Feature | Checkout API | Payment Links | | --- | --- | --- | | Custom metadata | Full support (key/value pairs) | Limited to `client_reference_id` | | Subscription metadata | Supported via `subscription_data` | Not supported | | Session ID tracking | Direct metadata field | URL parameter (less reliable) | | Server-side control | Full | None | For subscriptions, Payment Links do not carry metadata forward to future invoices. Only the initial payment will have attribution data. If you need subscription revenue tracking, use the [Checkout Sessions API](/docs/revenue-attribution/stripe-checkout#subscriptions) instead. ## Verify 1. Open your site and inspect a Stripe Payment Link — the URL should include `client_reference_id` and `engagetrack_session_id` parameters 2. Click the link and complete a test purchase using card `4242 4242 4242 4242` 3. Check your EngageTrack dashboard → **Revenue** tab for the payment 4. Verify the payment is attributed to the correct traffic source If the payment appears but without source attribution, the visitor ID was not passed correctly. Check that: - The EngageTrack SDK is loaded before the snippet runs - `window.engagetrack.getVisitorId()` returns a non-empty string - The URL parameters are present when clicking the link --- URL: https://engagetrack.net/docs/revenue-attribution/stripe-payment-intent.md --- title: Stripe PaymentIntent description: Set up revenue attribution with Stripe PaymentIntent for custom checkout flows. order: 4 --- # Stripe PaymentIntent If you are building a custom checkout form with Stripe Elements, you create PaymentIntents on the server. This guide shows how to attach EngageTrack metadata to the PaymentIntent so revenue is attributed correctly. ## How It Works 1. Your client-side code reads `engagetrack_visitor_id` and `engagetrack_session_id` from the SDK and sends them to your server 2. Your server creates a PaymentIntent with these values in the `metadata` field 3. After payment, Stripe sends a `payment_intent.succeeded` webhook to EngageTrack 4. EngageTrack reads the metadata and attributes the revenue ## Step 1: Send IDs from the Client When your checkout form loads, read the EngageTrack IDs and include them in the request to your server: ```javascript const visitorId = window.engagetrack?.getVisitorId() || ""; const sessionId = window.engagetrack?.getSessionId() || ""; const response = await fetch("/api/create-payment-intent", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ amount: 2999, // $29.99 in cents engagetrack_visitor_id: visitorId, engagetrack_session_id: sessionId, }), }); const { clientSecret } = await response.json(); // Use clientSecret with Stripe Elements to confirm payment ``` ## Step 2: Create the PaymentIntent with Metadata ### Node.js / Express ```javascript import Stripe from "stripe"; const stripe = new Stripe(process.env.STRIPE_SECRET_KEY); app.post("/api/create-payment-intent", async (req, res) => { const { amount, engagetrack_visitor_id, engagetrack_session_id } = req.body; const paymentIntent = await stripe.paymentIntents.create({ amount, currency: "usd", metadata: { engagetrack_visitor_id: engagetrack_visitor_id || "", engagetrack_session_id: engagetrack_session_id || "", }, }); res.json({ clientSecret: paymentIntent.client_secret }); }); ``` ### Next.js App Router (Route Handler) ```typescript import { NextRequest, NextResponse } from "next/server"; import Stripe from "stripe"; const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!); export async function POST(request: NextRequest) { const { amount, engagetrack_visitor_id, engagetrack_session_id } = await request.json(); const paymentIntent = await stripe.paymentIntents.create({ amount, currency: "usd", metadata: { engagetrack_visitor_id: engagetrack_visitor_id ?? "", engagetrack_session_id: engagetrack_session_id ?? "", }, }); return NextResponse.json({ clientSecret: paymentIntent.client_secret }); } ``` The SDK stores IDs in browser storage (not cookies), so the client-to-server approach shown above is the recommended pattern. Read the IDs with `window.engagetrack.getVisitorId()` and `window.engagetrack.getSessionId()`, then send them to your server in the request body. ## Step 3: Set Up the Webhook Add the EngageTrack webhook endpoint in your Stripe dashboard: 1. Go to [Stripe Dashboard → Developers → Webhooks](https://dashboard.stripe.com/webhooks) 2. Click **Add endpoint** 3. Enter the webhook URL: ``` https://api.engagetrack.net/api/v1/webhooks/revenue/stripe/{YOUR_SITE_PUBLIC_ID} ``` 4. Under **Events to send**, select: - `payment_intent.succeeded` - `charge.refunded` 5. Click **Add endpoint** ## Stripe Elements Example Here is a complete client-side example using Stripe Elements with React: ```tsx import { useState, useEffect } from "react"; import { loadStripe } from "@stripe/stripe-js"; import { Elements, PaymentElement, useStripe, useElements, } from "@stripe/react-stripe-js"; const stripePromise = loadStripe( process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!, ); function CheckoutForm() { const stripe = useStripe(); const elements = useElements(); const [loading, setLoading] = useState(false); async function handleSubmit(e: React.FormEvent) { e.preventDefault(); if (!stripe || !elements) return; setLoading(true); const { error } = await stripe.confirmPayment({ elements, confirmParams: { return_url: "https://yoursite.com/success", }, }); if (error) { console.error(error.message); } setLoading(false); } return (
); } export default function CheckoutPage() { const [clientSecret, setClientSecret] = useState(""); useEffect(() => { const visitorId = window.engagetrack?.getVisitorId() || ""; const sessionId = window.engagetrack?.getSessionId() || ""; fetch("/api/create-payment-intent", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ amount: 2999, engagetrack_visitor_id: visitorId, engagetrack_session_id: sessionId, }), }) .then((res) => res.json()) .then(({ clientSecret }) => setClientSecret(clientSecret)); }, []); if (!clientSecret) return
Loading checkout...
; return ( ); } ``` ## Verify 1. Open your site and navigate to the custom checkout page 2. Open DevTools → Console and run `window.engagetrack.getVisitorId()` to confirm the SDK is loaded and returning an ID 3. Complete a test payment using card `4242 4242 4242 4242` 4. Check your EngageTrack dashboard → **Revenue** tab 5. Confirm the payment appears and is attributed to your traffic source If the payment is not attributed: - Verify that the PaymentIntent metadata contains the correct keys (check in Stripe Dashboard → Payments → select payment → Metadata section) - Ensure the webhook endpoint is receiving events (Stripe Dashboard → Webhooks → recent deliveries) - Confirm you selected `payment_intent.succeeded` when adding the webhook endpoint --- URL: https://engagetrack.net/docs/revenue-attribution/lemonsqueezy.md --- title: LemonSqueezy description: Set up revenue attribution with LemonSqueezy. order: 5 --- # LemonSqueezy LemonSqueezy is a merchant of record that handles payments, taxes, and subscriptions. This guide shows how to pass EngageTrack visitor and session IDs through LemonSqueezy's `custom_data` field for revenue attribution. ## How It Works 1. The EngageTrack SDK generates a visitor ID and session ID (stored in browser storage, accessible via the SDK's JavaScript API) 2. When creating a checkout, you pass these values in the `custom_data` field 3. After payment, LemonSqueezy sends a webhook to EngageTrack with the custom data 4. EngageTrack reads the visitor ID and attributes the revenue to the traffic source ## Checkout API ### Node.js / Express ```javascript import { lemonSqueezySetup, createCheckout } from "@lemonsqueezy/lemonsqueezy.js"; lemonSqueezySetup({ apiKey: process.env.LEMONSQUEEZY_API_KEY }); app.post("/create-checkout", async (req, res) => { // Receive visitor/session IDs from the client request body const { engagetrack_visitor_id: visitorId, engagetrack_session_id: sessionId } = req.body; const { data } = await createCheckout(process.env.LEMONSQUEEZY_STORE_ID, { productOptions: { redirectUrl: "https://yoursite.com/success", }, checkoutData: { custom: { engagetrack_visitor_id: visitorId, engagetrack_session_id: sessionId, }, }, }); res.json({ url: data.data.attributes.url }); }); ``` ### Next.js App Router (Route Handler) ```typescript import { NextRequest, NextResponse } from "next/server"; import { lemonSqueezySetup, createCheckout } from "@lemonsqueezy/lemonsqueezy.js"; lemonSqueezySetup({ apiKey: process.env.LEMONSQUEEZY_API_KEY! }); export async function POST(request: NextRequest) { // Receive visitor/session IDs from the client request body const { variant_id, engagetrack_visitor_id, engagetrack_session_id } = await request.json(); const visitorId = engagetrack_visitor_id ?? ""; const sessionId = engagetrack_session_id ?? ""; const { data } = await createCheckout(process.env.LEMONSQUEEZY_STORE_ID!, { productOptions: { redirectUrl: "https://yoursite.com/success", }, checkoutData: { variantId: Number(variant_id), custom: { engagetrack_visitor_id: visitorId, engagetrack_session_id: sessionId, }, }, }); return NextResponse.json({ url: data!.data.attributes.url }); } ``` LemonSqueezy uses `custom_data` (accessed via the `custom` field in the SDK) to pass arbitrary data through the checkout. EngageTrack expects the keys `engagetrack_visitor_id` and `engagetrack_session_id` inside this object. ## Checkout Links If you use LemonSqueezy Checkout Links (no server code), append the custom data as URL parameters: ```html Buy Now ``` The URL parameter syntax for LemonSqueezy checkout links uses bracket notation: `checkout[custom][engagetrack_visitor_id]`. This is how LemonSqueezy maps URL parameters to the `custom_data` field. ## Set Up the Webhook 1. Go to [LemonSqueezy Dashboard → Settings → Webhooks](https://app.lemonsqueezy.com/settings/webhooks) 2. Click **Add endpoint** 3. Enter the webhook URL: ``` https://api.engagetrack.net/api/v1/webhooks/revenue/lemonsqueezy/{YOUR_SITE_PUBLIC_ID} ``` 4. Under **Events**, select: - `order_created` - `subscription_payment_success` - `order_refunded` 5. Enter a signing secret and save it — you will need this when connecting LemonSqueezy in EngageTrack 6. Click **Save** If you connected LemonSqueezy via the EngageTrack dashboard (Site Settings → Revenue), the webhook is registered automatically and you can skip this step. ## Verify 1. Open your site and confirm the SDK is loaded by running `window.engagetrack.getVisitorId()` in the browser console 2. Complete a test purchase using LemonSqueezy's [test mode](https://docs.lemonsqueezy.com/guides/developer-guide/testing) 3. Go to your EngageTrack dashboard → **Revenue** tab 4. The test payment should appear within a few seconds, attributed to your traffic source If the payment appears without attribution: - Check the LemonSqueezy webhook logs for delivery errors (LemonSqueezy Dashboard → Webhooks → select endpoint) - Verify the `custom_data` field in the webhook payload contains `engagetrack_visitor_id` - Ensure the cookie values are non-empty when creating the checkout --- URL: https://engagetrack.net/docs/revenue-attribution/paddle.md --- title: Paddle description: Set up revenue attribution with Paddle. order: 6 --- # Paddle Paddle is a merchant of record that handles payments, taxes, and subscriptions globally. This guide shows how to pass EngageTrack visitor and session IDs through Paddle's `custom_data` field for revenue attribution. ## How It Works 1. The EngageTrack SDK generates a visitor ID and session ID (stored in browser storage, accessible via the SDK's JavaScript API) 2. When opening a Paddle checkout, you pass these values in the `custom_data` field 3. After payment, Paddle sends a webhook to EngageTrack with the custom data 4. EngageTrack reads the visitor ID and attributes the revenue to the traffic source ## Overlay Checkout (Paddle.js) The most common Paddle integration uses the overlay checkout via Paddle.js. Pass the EngageTrack IDs in the `customData` option: ```html ``` ### React / Next.js ```tsx "use client"; import { initializePaddle, type Paddle } from "@paddle/paddle-js"; import { useEffect, useState } from "react"; export default function CheckoutButton({ priceId }: { priceId: string }) { const [paddle, setPaddle] = useState(null); useEffect(() => { initializePaddle({ token: process.env.NEXT_PUBLIC_PADDLE_CLIENT_TOKEN!, }).then(setPaddle); }, []); function handleCheckout() { if (!paddle) return; const visitorId = window.engagetrack?.getVisitorId() || ""; const sessionId = window.engagetrack?.getSessionId() || ""; paddle.Checkout.open({ items: [{ priceId, quantity: 1 }], customData: { engagetrack_visitor_id: visitorId, engagetrack_session_id: sessionId, }, settings: { successUrl: "https://yoursite.com/success", }, }); } return ; } ``` Paddle uses `custom_data` to pass arbitrary data through the checkout. EngageTrack expects the keys `engagetrack_visitor_id` and `engagetrack_session_id` inside this object. ## Checkout API (Server-Side) If you create transactions server-side using the Paddle API, attach the custom data there: ```javascript import { Paddle } from "@paddle/paddle-node-sdk"; const paddle = new Paddle(process.env.PADDLE_API_KEY); app.post("/create-checkout", async (req, res) => { // Receive visitor/session IDs from the client request body const { engagetrack_visitor_id: visitorId, engagetrack_session_id: sessionId } = req.body; const transaction = await paddle.transactions.create({ items: [ { priceId: "pri_xxxxxxxxxxxxx", quantity: 1, }, ], customData: { engagetrack_visitor_id: visitorId, engagetrack_session_id: sessionId, }, }); res.json({ transactionId: transaction.id }); }); ``` ## Set Up the Webhook 1. Go to [Paddle Dashboard → Developer Tools → Notifications](https://vendors.paddle.com/notifications) 2. Click **New destination** 3. Select **Webhook** as the type 4. Enter the webhook URL: ``` https://api.engagetrack.net/api/v1/webhooks/revenue/paddle/{YOUR_SITE_PUBLIC_ID} ``` 5. Under **Events**, select: - `transaction.completed` (handles both one-time payments and subscription renewals — renewals are detected when `origin` is `subscription_recurring`) - `adjustment.created` (for refunds) 6. Click **Save** If you connected Paddle via the EngageTrack dashboard (Site Settings → Revenue), the webhook is registered automatically and you can skip this step. ## Verify 1. Open your site and confirm the SDK is loaded by running `window.engagetrack.getVisitorId()` in the browser console 2. Complete a test purchase using Paddle's [sandbox environment](https://developer.paddle.com/concepts/platform/environments) 3. Go to your EngageTrack dashboard → **Revenue** tab 4. The test payment should appear within a few seconds, attributed to your traffic source If the payment appears without attribution: - Open the Paddle transaction in your Paddle dashboard and check the `custom_data` field contains `engagetrack_visitor_id` - Verify webhook delivery in Paddle Dashboard → Developer Tools → Notifications → select destination → Event logs - Ensure the EngageTrack SDK is loaded before `Paddle.Checkout.open()` is called --- URL: https://engagetrack.net/docs/revenue-attribution/polar.md --- title: Polar description: Set up revenue attribution with Polar. order: 7 --- # Polar Polar is a payment platform for developers and open-source projects. This guide shows how to pass EngageTrack visitor and session IDs through Polar's `metadata` field for revenue attribution. ## How It Works 1. The EngageTrack SDK generates a visitor ID and session ID (stored in browser storage, accessible via the SDK's JavaScript API) 2. When creating a Polar checkout, you pass these values in the `metadata` field 3. After payment, Polar sends a webhook to EngageTrack with the metadata 4. EngageTrack reads the visitor ID and attributes the revenue to the traffic source ## Checkout API ### Node.js / Express ```javascript import { Polar } from "@polar-sh/sdk"; const polar = new Polar({ accessToken: process.env.POLAR_ACCESS_TOKEN }); app.post("/create-checkout", async (req, res) => { // Receive visitor/session IDs from the client request body const { engagetrack_visitor_id: visitorId, engagetrack_session_id: sessionId } = req.body; const checkout = await polar.checkouts.create({ productPriceId: "price_xxxxxxxxxxxxx", successUrl: "https://yoursite.com/success", metadata: { engagetrack_visitor_id: visitorId, engagetrack_session_id: sessionId, }, }); res.json({ url: checkout.url }); }); ``` ### Next.js App Router (Route Handler) ```typescript import { NextRequest, NextResponse } from "next/server"; import { Polar } from "@polar-sh/sdk"; const polar = new Polar({ accessToken: process.env.POLAR_ACCESS_TOKEN! }); export async function POST(request: NextRequest) { // Receive visitor/session IDs from the client request body const { price_id, engagetrack_visitor_id, engagetrack_session_id } = await request.json(); const visitorId = engagetrack_visitor_id ?? ""; const sessionId = engagetrack_session_id ?? ""; const checkout = await polar.checkouts.create({ productPriceId: price_id, successUrl: "https://yoursite.com/success", metadata: { engagetrack_visitor_id: visitorId, engagetrack_session_id: sessionId, }, }); return NextResponse.json({ url: checkout.url }); } ``` Polar uses a `metadata` field (not `custom_data`) to pass arbitrary key-value pairs through the checkout. EngageTrack expects the keys `engagetrack_visitor_id` and `engagetrack_session_id`. ## Checkout Links If you use Polar Checkout Links, append the metadata as URL parameters: ```html Buy Now ``` ## Set Up the Webhook 1. Go to [Polar Dashboard → Settings → Webhooks](https://polar.sh/settings/webhooks) 2. Click **Add endpoint** 3. Enter the webhook URL: ``` https://api.engagetrack.net/api/v1/webhooks/revenue/polar/{YOUR_SITE_PUBLIC_ID} ``` 4. Under **Events**, select: - `order.created` - `subscription.updated` - `refund.created` 5. Click **Save** If you connected Polar via the EngageTrack dashboard (Site Settings → Revenue), the webhook is registered automatically and you can skip this step. ## Verify 1. Open your site and confirm the SDK is loaded by running `window.engagetrack.getVisitorId()` in the browser console 2. Complete a test purchase using Polar's [sandbox mode](https://docs.polar.sh/developers/sandbox) 3. Go to your EngageTrack dashboard → **Revenue** tab 4. The test payment should appear within a few seconds, attributed to your traffic source If the payment appears without attribution: - Check the Polar webhook logs for delivery errors (Polar Dashboard → Settings → Webhooks → select endpoint) - Verify the `metadata` field in the webhook payload contains `engagetrack_visitor_id` - Ensure the EngageTrack SDK is loaded and the cookie values are non-empty when creating the checkout --- URL: https://engagetrack.net/docs/analytics/dashboard-overview.md --- title: Dashboard Overview description: Understand the metrics, charts, and breakdowns available in your EngageTrack analytics dashboard. order: 1 --- # Dashboard Overview The EngageTrack dashboard gives you a real-time, centralized view of your website's traffic and performance. All data is scoped to a single site within your organization. ## Key Metrics The top bar displays five headline KPIs, each with a comparison percentage to the previous period: | Metric | Description | | ----------------- | ------------------------------------------ | | **Visitors** | Unique visitors | | **Pageviews** | Total page loads across all visitors | | **Bounce Rate** | Percentage of single-page sessions | | **Visit Duration**| Average time spent per session | | **Views/Visit** | Average number of pages viewed per session | Comparisons are always against the immediately preceding period of equal length. For example, selecting "Last 7 days" compares to the 7 days before that. ## Time-Series Chart Below the KPIs, a line chart shows visitors, pageviews, or sessions over time. The granularity adjusts automatically based on the selected period. A faded overlay shows the previous period for at-a-glance comparison. ## Breakdown Cards ### Sources Traffic is grouped into semantic **channels** (Organic Search, Paid, Social, Direct, Email, Referral) and further broken down by: - **Referrers** — individual domains sending traffic - **Campaigns** — UTM campaigns (`utm_campaign` parameter) - **Channels** — enriched channel view with top sub-sources and revenue per channel ### Pages - **Top Pages** — most visited page paths - **Entry Pages** — where visitors land first - **Exit Pages** — where visitors leave ### Locations Geographic distribution at three levels: - **Country** - **Region** — state or province - **City** A 3D globe visualization shows real-time visitor locations. ### Devices - **Device** — Desktop, Mobile, or Tablet - **Browser** — Chrome, Firefox, Safari, etc. - **OS** — Windows, macOS, Android, iOS, etc. ## Realtime The realtime widget shows the number of visitors currently active on your site. A live globe displays active visitor coordinates in real-time. ## Date Picker All dashboard data can be filtered by period: - **Today** — current day so far - **Yesterday** — the previous full day - **7d** — last 7 days - **30d** — last 30 days - **90d** — last 90 days - **12mo** — last 12 months - **Custom** — pick a specific start and end date --- URL: https://engagetrack.net/docs/analytics/filtering.md --- title: Filtering & Segmentation description: Filter your analytics data by country, page, source, device, browser, OS, and more. order: 2 --- # Filtering & Segmentation EngageTrack supports powerful filtering across all analytics views. Filters let you drill down into specific segments — for example, "visitors from Germany using Chrome on mobile." ## Available Filter Dimensions | Dimension | Example Values | | -------------- | ------------------------------------------------- | | Country | `US`, `DE`, `RO` | | Region | `California`, `Bavaria` | | City | `San Francisco`, `Bucharest` | | Page | `/pricing`, `/blog/my-post` | | Entry Page | `/`, `/landing` | | Source | `google`, `twitter` | | UTM Source | `newsletter`, `google` | | UTM Medium | `cpc`, `email`, `social` | | UTM Campaign | `spring-sale`, `launch` | | Referrer | `github.com`, `reddit.com` | | Browser | `Chrome`, `Firefox`, `Safari` | | OS | `Windows`, `macOS`, `Android` | | Device | `Desktop`, `Mobile`, `Tablet` | | Event Name | `signup`, `purchase` | ## How to Apply Filters 1. Click **+ Add filter** above the chart 2. Select a dimension (e.g., Country) 3. Start typing to search for values — the dashboard suggests matching values as you type 4. Select one or more values 5. The entire dashboard updates to reflect only matching traffic Multiple filters are combined with **AND** logic — all conditions must match. Filters persist across all tabs (Sources, Pages, Locations, Devices) so you can explore different breakdowns for the same segment. --- URL: https://engagetrack.net/docs/advanced/script-configuration.md --- title: Script Configuration description: Complete reference for all tracking script configuration options. order: 1 --- # Script Configuration The EngageTrack tracking script is configured entirely through HTML `data-*` attributes on the ` ``` ## Script Attributes Reference | Attribute | Type | Default | Description | | --------- | ---- | ------- | ----------- | | `data-site-id` | string | — | **Required.** Your site ID from the EngageTrack dashboard. Also accepts `data-site` as an alias. | | `data-api` | string | `https://api.engagetrack.net/api/v1/event` | Custom event endpoint URL. Use this when [proxying](/docs/proxy/overview) the SDK through your own domain. | | `data-outbound` | `"true"` / `"false"` | `"true"` | Track clicks on links to external domains. | | `data-downloads` | `"true"` / `"false"` | `"true"` | Track file download clicks (pdf, doc, zip, exe, etc.). | | `data-forms` | `"true"` / `"false"` | `"true"` | Track form submissions. Auth-related forms are automatically excluded. | | `data-phone` | `"true"` / `"false"` | `"true"` | Track clicks on `tel:` phone links. | | `data-hash` | `"true"` / `"false"` | `"false"` | Enable hash-based routing mode. When `"true"`, the full URL including `#hash` is tracked as the page path. | | `data-persistence` | `"memory"` / `"storage"` | `"memory"` | Tracking persistence mode. **`"memory"`** (default): zero device storage — session ID lives in a JS variable, lost on tab close. No consent banner needed. **`"storage"`**: persistent visitor ID in `localStorage`, session in `sessionStorage`. Enables multi-day visitor tracking but requires a consent banner in the EU. | | `data-debug` | `"true"` / `"false"` | `"false"` | Log all tracking events to the browser console. | | `data-allowed-hostnames` | string | `""` | Comma-separated list of hostnames for [cross-domain tracking](/docs/advanced/cross-domain). Requires `data-persistence="storage"`. | | `data-exclude` | string | `""` | Comma-separated list of path patterns to exclude from pageview tracking (e.g., `/dashboard/*,/admin/*`). Supports `*` wildcards. Custom events and purchases are never excluded. | The `data-site-id` attribute is required. Without it, the script will not initialize and will log a warning to the console. ## HTML Element Attributes These attributes can be added to any HTML element to trigger tracking behavior. ### Goal Tracking | Attribute | Description | | --------- | ----------- | | `data-goal` | Fires a custom goal event when the element is clicked. Value is the goal name (lowercase, numbers, hyphens, underscores, max 64 chars). | | `data-goal-*` | Attach custom properties to the goal. The suffix becomes the property name (kebab-case is converted to snake_case). Max 10 properties per goal. | ```html ``` Goal names must match the pattern `[a-z0-9_-]` and be at most 64 characters. Property values are truncated to 255 characters. ### Scroll Tracking | Attribute | Description | | --------- | ----------- | | `data-scroll` | Fires a custom event when the element scrolls into view (50% visibility threshold). Value is the goal name. Each goal fires only once per page load. | ```html

Pricing

``` Scroll tracking uses the `IntersectionObserver` API. Goals reset on SPA navigation, so they can fire again on the next page. ## Configuration Examples ### Development Setup Track localhost traffic with debug logging enabled: ```html ``` Open your browser console to see all events being sent in real time. ### Production with Proxy Serve the SDK through your own domain to bypass ad blockers: ```html ``` > See the [Proxy Setup guide](/docs/proxy/overview) for full instructions. ### Persistent Tracking (Storage Mode) Enable multi-day visitor tracking. Requires a consent banner in the EU: ```html ``` Storage mode writes a visitor ID to `localStorage` and session data to `sessionStorage`. Under the ePrivacy Directive, this requires informed consent before the script loads for EU visitors. ### Cross-Domain Tracking Track visitors across multiple domains as a single session. Requires `data-persistence="storage"`: ```html ``` > See the [Cross-Domain Tracking guide](/docs/advanced/cross-domain) for setup details. ### Hash-Based Navigation For apps using hash-based routing (e.g., `/#/dashboard`, `/#/settings`): ```html ``` ### Minimal Tracking Disable all automatic tracking except pageviews: ```html ``` --- URL: https://engagetrack.net/docs/advanced/cross-domain.md --- title: Cross-Domain Tracking description: Track visitors across multiple domains with seamless session stitching. order: 2 --- # Cross-Domain Tracking By default, EngageTrack treats each domain as a separate context. Cross-domain tracking lets you follow a single visitor across multiple domains (e.g., `www.example.com` to `checkout.example.com`) as one continuous session. Cross-domain tracking requires **storage mode** (`data-persistence="storage"`) on both domains. In the default memory mode, there is no persistent visitor ID to pass between domains. Storage mode requires a consent banner in the EU. ## How It Works 1. You list the destination domains in the `data-allowed-hostnames` attribute on the **source** domain 2. When a visitor clicks a link to an allowed hostname, the SDK appends `_et_vid` (visitor ID) and `_et_sid` (session ID) as URL parameters 3. On the **destination** domain, the SDK reads those parameters, hydrates the visitor and session IDs into `localStorage`/`sessionStorage`, and removes the parameters from the URL The result is a seamless session that spans both domains. ## Setup ### Step 1: Configure the Source Domain On every domain that links to another domain you own, add the destination hostnames to `data-allowed-hostnames`: ```html ``` List only the exact hostnames (no protocol, no paths). Separate multiple hostnames with commas. Both `data-persistence="storage"` and `data-allowed-hostnames` are required on the source domain. ### Step 2: Install the SDK on the Destination Domain The destination domain must also have the EngageTrack script installed with the **same site ID**: ```html ``` The SDK automatically detects `_et_vid` and `_et_sid` in the URL, hydrates the visitor identity into `localStorage`/`sessionStorage`, and cleans the URL. ### Step 3: Use Regular Links No special link markup is needed. The SDK intercepts clicks on outbound links and decorates them automatically: ```html Complete Purchase ``` Cross-domain links opened via `window.open()` or programmatic navigation are not automatically decorated. For those cases, build the URL manually using `window.engagetrack.getVisitorId()` and `window.engagetrack.getSessionId()`. ### Programmatic Navigation If you navigate to a cross-domain URL with JavaScript: ```javascript const vid = window.engagetrack.getVisitorId(); const sid = window.engagetrack.getSessionId(); const url = new URL("https://checkout.example.com/buy"); url.searchParams.set("_et_vid", vid); url.searchParams.set("_et_sid", sid); window.location.href = url.toString(); ``` ## Bidirectional Tracking If visitors can navigate in both directions (e.g., `www` to `checkout` and back), add `data-allowed-hostnames` on **both** domains: ```html ``` ## Verify It's Working 1. Enable debug mode on both domains by adding `data-debug="true"` to the script tag 2. Open the browser console on the source domain 3. Click a link to the destination domain 4. Look for `[EngageTrack] Cross-domain link decorated:` in the console — this confirms the URL parameters were appended 5. On the destination domain, check for `[EngageTrack] Cross-domain: hydrated visitor` and `hydrated session` messages 6. Verify both domains report the same visitor ID by calling `window.engagetrack.getVisitorId()` in the console on each domain --- URL: https://engagetrack.net/docs/advanced/subdomain-tracking.md --- title: Subdomain Tracking description: Track visitors across subdomains of the same root domain. order: 3 --- # Subdomain Tracking EngageTrack handles subdomain tracking automatically in most cases. This guide covers how to configure tracking for different subdomain setups. ## Default Behavior In the default **memory mode**, the SDK uses no device storage at all — visitor identification is handled server-side via a daily-rotating hash. This means all subdomains are treated equally: visitors are identified by the same hash within a single day, regardless of which subdomain they visit. In **storage mode** (`data-persistence="storage"`), the SDK stores the visitor ID in `localStorage`. Since `localStorage` is scoped to the exact origin, different subdomains maintain separate storage: - **Same-origin pages** (e.g., `www.example.com/blog` and `www.example.com/app`) share identity automatically - **Different subdomains** (e.g., `www.example.com` and `app.example.com`) do **not** share `localStorage` by default — each subdomain will generate its own visitor ID The SDK also filters out self-referrals between subdomains. If a visitor navigates from `blog.example.com` to `app.example.com`, the referrer is treated as direct — not as an external source. ## Setup for Separate Tracking If you want to track each subdomain as an independent site with its own dashboard, create a separate site in EngageTrack for each subdomain and use different site IDs: ```html ``` Each site will have its own analytics, visitors, and revenue data. ## Setup for Unified Tracking To track all subdomains under a single site in EngageTrack, use the **same site ID** on every subdomain: ```html ``` All pageviews and events from every subdomain will appear in the same dashboard. You can filter by hostname in the **Pages** report to isolate traffic from a specific subdomain. In storage mode, `localStorage` is scoped to the exact origin, so visitor IDs will differ between subdomains. To stitch visitor sessions across subdomains, use [cross-domain tracking](/docs/advanced/cross-domain) with `data-persistence="storage"` and `data-allowed-hostnames`. In the default memory mode, the server-side hash naturally handles same-day visitor identification across subdomains. ## Filtering by Subdomain When using unified tracking, you can segment data by subdomain in the dashboard: 1. Go to the **Pages** report 2. Use the hostname filter to select a specific subdomain 3. All metrics (visitors, pageviews, bounce rate) will be scoped to that subdomain You can also create [goals](/docs/tracking/goals) that target specific subdomains by filtering on the page URL. --- URL: https://engagetrack.net/docs/advanced/user-identification.md --- title: User Identification description: Connect anonymous visitors to known user profiles for enhanced analytics. order: 4 --- # User Identification EngageTrack tracks visitors anonymously by default. The Identify API lets you connect an anonymous visitor to a known user profile after they log in or sign up, enriching your analytics with user-level data. ## The Identify API ```javascript window.engagetrack.identify(userId, { name: "Jane Smith", email: "jane@example.com", avatar: "https://example.com/avatars/jane.jpg", custom: { plan: "pro", company: "Acme Inc", }, }); ``` ### Parameters | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | | `userId` | string | Yes | A unique, stable identifier for the user (e.g., database ID, auth provider ID). | | `traits.name` | string | No | Display name. | | `traits.email` | string | No | Email address. Used for [email-based revenue attribution](/docs/tracking/revenue#attribution-models). | | `traits.avatar` | string | No | URL to the user's avatar image. Displayed in the visitor timeline. | | `traits.custom` | object | No | Key-value pairs of custom properties (e.g., plan, company, role). | ## When to Call Identify Call `identify()` after the user's identity is confirmed — typically right after login or signup: ```javascript // After successful login async function onLogin(credentials) { const user = await api.login(credentials); // Identify the visitor with EngageTrack window.engagetrack.identify(user.id, { name: user.name, email: user.email, }); } ``` ```javascript // After successful signup async function onSignup(formData) { const user = await api.register(formData); window.engagetrack.identify(user.id, { name: user.name, email: user.email, custom: { signup_source: "landing-page", }, }); } ``` You only need to call `identify()` once per session. The SDK links the current anonymous visitor ID to the user profile on the server. ### React / Next.js Example ```tsx "use client"; import { useEffect } from "react"; import { useAuth } from "@/hooks/useAuth"; export function IdentifyUser() { const { user } = useAuth(); useEffect(() => { if (user && typeof window !== "undefined" && window.engagetrack) { window.engagetrack.identify(user.id, { name: user.name, email: user.email, avatar: user.avatar, }); } }, [user]); return null; } ``` Place this component inside your authenticated layout so it runs whenever a logged-in user loads the page. ## How It Works When you call `identify()`, the SDK sends a POST request to the `/api/v1/identify` endpoint with: - The current anonymous `visitor_uid` (from `localStorage` — requires storage mode) - The `user_id` you provided - Any traits (name, email, avatar, custom) The server links the anonymous visitor record to the user profile. All past and future events for that visitor are associated with the identified user. `identify()` requires **storage mode** (`data-persistence="storage"`) because it needs a persistent visitor ID to link across sessions. In the default memory mode, calling `identify()` will log a warning and return without effect. ## Visitor Timeline Enrichment Once a visitor is identified, their profile in the **Visitors** dashboard shows: - **Name and avatar** instead of an anonymous ID - **Email address** for quick reference - **Custom properties** as metadata tags - **Full event timeline** including pre-identification pageviews ## Revenue Attribution Identified users unlock email-based revenue attribution. When a payment webhook arrives with an email address, EngageTrack can match it to an identified visitor — even if the `engagetrack_visitor_id` metadata was not included in the payment. > See [Revenue Attribution](/docs/tracking/revenue#attribution-models) for the full attribution priority chain. --- URL: https://engagetrack.net/docs/advanced/exclude-visits.md --- title: Exclude Visits description: Filter out internal traffic, bots, and test environments from your analytics. order: 5 --- # Exclude Visits Keep your analytics clean by excluding internal team visits, development traffic, and bots from your data. ## Self-Exclusion (Browser) The simplest way to exclude yourself is from the browser console on your tracked site. ### Using the SDK Method ```javascript // Disable tracking for this browser window.engagetrack.ignore(); // Re-enable tracking window.engagetrack.unignore(); ``` Both methods require a page reload to take effect. ### Using localStorage Directly ```javascript // Disable tracking localStorage.setItem("engagetrack_ignore", "true"); // Re-enable tracking localStorage.removeItem("engagetrack_ignore"); ``` The exclusion flag is stored in `localStorage`, so it persists across sessions but is specific to that browser. You need to set it on each browser and device you use. ### Bookmark Shortcut Create a browser bookmark with this URL to toggle exclusion with one click: ``` javascript:void(localStorage.getItem('engagetrack_ignore')==='true'?(localStorage.removeItem('engagetrack_ignore'),alert('EngageTrack: Tracking enabled. Reload the page.')):(localStorage.setItem('engagetrack_ignore','true'),alert('EngageTrack: Tracking disabled. Reload the page.'))) ``` ## IP Exclusion Exclude traffic from specific IP addresses or ranges in the dashboard: 1. Go to **Site Settings -> Tracking** 2. Under **Excluded IPs**, add IP addresses or CIDR ranges 3. Traffic from those IPs will be silently dropped Common use cases: - Office IP addresses - VPN exit nodes used by your team - CI/CD server IPs IP exclusion is applied server-side, so excluded traffic never appears in your analytics data at all. ## Path Exclusion Exclude specific pages or URL patterns from being tracked: 1. Go to **Site Settings -> Tracking** 2. Under **Excluded Paths**, add URL patterns Patterns support wildcards: | Pattern | Matches | | ------- | ------- | | `/admin/*` | All pages under `/admin/` | | `/internal` | Exact match for `/internal` | | `/staging/*` | All staging pages | ## Hostname Exclusion If you have the script installed on staging or development environments and want to exclude that traffic: 1. Go to **Site Settings -> Tracking** 2. Under **Allowed Hostnames**, list only the production hostnames Any traffic from hostnames not in the list will be ignored. If you leave the allowed hostnames list empty, traffic from all hostnames is accepted. Add at least your production domain to enable hostname filtering. ## Verify Exclusion To confirm your visits are being excluded: 1. Add `data-debug="true"` to the script tag (or use a development environment) 2. Open the browser console 3. If you have `engagetrack_ignore` set, you will see: `[EngageTrack] Tracking disabled via engagetrack_ignore flag` 4. Check the **Real-time** dashboard view — your visits should not appear --- URL: https://engagetrack.net/docs/advanced/data-export.md --- title: Data Export description: Export your analytics data for custom analysis and reporting. order: 6 --- # Data Export EngageTrack gives you full access to your analytics data. Export it as CSV from the dashboard or use the API for programmatic access. ## CSV Export from Dashboard Every report in the EngageTrack dashboard has a **Download CSV** button: 1. Navigate to the report you want to export (Pages, Sources, Countries, etc.) 2. Apply any filters or date range you need 3. Click the **Download CSV** button in the top-right corner The exported CSV includes all rows matching your current filters, not just the visible page. ## API-Based Export Use the analytics export endpoint to fetch data programmatically: ```bash curl -X GET "https://api.engagetrack.net/api/v1/analytics/export?site_id=YOUR_SITE_ID&period=30d&metric=pageviews" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Accept: text/csv" ``` ### Query Parameters | Parameter | Type | Description | | --------- | ---- | ----------- | | `site_id` | string | Your site ID | | `period` | string | Time range: `7d`, `30d`, `90d`, `12mo`, or custom `2024-01-01,2024-01-31` | | `metric` | string | Export type: `pageviews`, `sources`, `countries`, `devices`, `events` | The response is a CSV file with appropriate `Content-Disposition` headers for download. API exports respect the same permissions as the dashboard. You need a valid API key with read access to the site. Generate one in **Site Settings -> API Keys**. ## Full Site Export Request a complete export of all raw event data for a site: ```bash curl -X POST "https://api.engagetrack.net/api/v1/exports/full" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "site_id": "YOUR_SITE_ID", "start_date": "2024-01-01", "end_date": "2024-12-31" }' ``` ### Response ```json { "export_id": "exp_abc123", "status": "processing", "estimated_rows": 150000, "download_url": null } ``` Full exports are processed asynchronously. You will receive an email with a download link when the export is ready. You can also poll the status: ```bash curl -X GET "https://api.engagetrack.net/api/v1/exports/exp_abc123" \ -H "Authorization: Bearer YOUR_API_KEY" ``` Full exports can be large. The download link expires after 24 hours. For ongoing data access, use the API-based export with specific date ranges instead. ## Export Data Format Full exports include one row per event with the following fields: | Field | Description | | ----- | ----------- | | `timestamp` | ISO 8601 event time | | `event_type` | `pageview`, `custom`, `outbound`, `download`, `form_submit`, `purchase`, etc. | | `url` | Page URL where the event occurred | | `referrer` | Referring URL (empty for direct traffic) | | `visitor_uid` | Anonymous visitor identifier | | `session_id` | Session identifier | | `event_name` | Custom event or goal name | | `properties` | JSON object of event properties | | `country` | Two-letter country code | | `device` | `desktop`, `mobile`, or `tablet` | | `browser` | Browser name | | `os` | Operating system | | `revenue` | Revenue amount (for purchase events) | | `currency` | Revenue currency code | --- URL: https://engagetrack.net/docs/advanced/email-reports.md --- title: Email Reports description: Receive automated analytics reports in your inbox. order: 7 --- # Email Reports Get a summary of your site's performance delivered to your inbox on a regular schedule — no need to log into the dashboard. ## Setting Up a Report 1. Go to **Site Settings -> Email Reports** 2. Click **New Report** 3. Configure the report: - **Frequency** — Daily, weekly (sent on Mondays), or monthly (sent on the 1st) - **Metrics** — Choose which metrics to include (visitors, pageviews, bounce rate, revenue, top pages, top sources) - **Comparison** — Include a comparison to the previous period (e.g., this week vs. last week) 4. Add recipients and click **Save** Reports are sent at 9:00 AM in the timezone configured for your site. Change your site timezone in **Site Settings -> General**. ## Customizing Report Content Each report can include any combination of the following sections: | Section | Description | | ------- | ----------- | | **Summary** | Total visitors, pageviews, bounce rate, and visit duration | | **Revenue** | Total revenue, number of purchases, average order value | | **Top Pages** | Top 10 pages by pageviews | | **Top Sources** | Top 10 traffic sources | | **Top Countries** | Top 10 countries by visitors | | **Goals** | Conversion counts for your tracked goals | Toggle sections on or off when creating or editing a report. ## Managing Recipients Reports can be sent to any email address — recipients do not need an EngageTrack account: - **Add recipients** when creating a report, or edit an existing report to add more - **Remove recipients** by clicking the remove icon next to their email - **Team members** with access to the site are suggested automatically Only site owners and admins can create and manage email reports. Team members with viewer access cannot modify report settings. ## Managing Reports View and manage all scheduled reports from **Site Settings -> Email Reports**: - **Pause** a report to temporarily stop delivery without deleting the configuration - **Edit** a report to change the frequency, metrics, or recipients - **Delete** a report to stop it permanently - **Send now** to trigger an immediate delivery for testing ## Example Report A weekly email report includes: - **Subject:** "EngageTrack Weekly Report — example.com — Mar 10-16, 2026" - **Summary metrics** with percentage change vs. the previous week - **Top 10 pages and sources** in a clean table format - **Revenue summary** if revenue tracking is enabled - A link to view the full dashboard for the reported period --- URL: https://engagetrack.net/docs/proxy/overview.md --- title: Proxy Setup description: Improve tracking accuracy by proxying the SDK through your own domain. order: 1 --- # Proxy Setup Proxying the EngageTrack SDK through your own domain improves tracking accuracy by preventing ad blockers from blocking the tracking script and API requests. ## Why Use a Proxy - **Ad blocker bypass** — Ad blockers maintain lists of known analytics domains. Serving the script from your own domain avoids these lists entirely. - **First-party context** — Requests to your own domain are treated as first-party by browsers, avoiding third-party restrictions. - **Privacy compliance** — Data stays within your infrastructure before being forwarded, which can simplify GDPR data processing documentation. ## How It Works A proxy setup involves two things: 1. **Serve the SDK script** from your domain instead of `cdn.engagetrack.net` 2. **Relay event data** from your domain to the EngageTrack API at `api.engagetrack.net` The visitor's browser only ever communicates with your domain. Your server forwards the requests to EngageTrack behind the scenes. ``` Browser → yourdomain.com/js/script.js → cdn.engagetrack.net/sdk.js Browser → yourdomain.com/api/event → api.engagetrack.net/api/v1/event ``` ## Updated Script Tag After setting up the proxy, update your script tag to use your proxy URLs: ```html ``` The `data-api` attribute tells the SDK to send events to your proxy endpoint instead of the default EngageTrack API. Make sure your proxy forwards the original client IP address in the `X-Forwarded-For` header. EngageTrack uses IP geolocation for country-level analytics. Without the real IP, all visitors will appear to come from your server's location. ## Proxy Guides Choose the guide that matches your stack: - [Next.js Proxy](/docs/proxy/nextjs) — Using rewrites or middleware - [Nginx Proxy](/docs/proxy/nginx) — Reverse proxy configuration - [Express.js Proxy](/docs/proxy/express) — Node.js middleware The proxy approach works with any server that can forward HTTP requests. The guides above cover the most common setups. The pattern is always the same: proxy the script file and the event endpoint. --- URL: https://engagetrack.net/docs/proxy/nextjs.md --- title: Next.js Proxy description: Set up an EngageTrack proxy with Next.js middleware or rewrites. order: 2 --- # Next.js Proxy There are two ways to proxy EngageTrack through a Next.js application: **rewrites** (simplest) or **middleware** (more control). ## Option 1: Rewrites (Recommended) Add rewrites to your `next.config.js` (or `next.config.ts`): ```javascript /** @type {import('next').NextConfig} */ const nextConfig = { async rewrites() { return [ { source: "/js/script.js", destination: "https://cdn.engagetrack.net/sdk.js", }, { source: "/api/event", destination: "https://api.engagetrack.net/api/v1/event", }, ]; }, }; module.exports = nextConfig; ``` Then update your script tag: ```html ``` Next.js rewrites automatically forward the client's IP address and headers, so geolocation works out of the box. ### Next.js App Router Component If you use the App Router, create a component to load the script: ```tsx // components/engagetrack.tsx export function EngageTrack() { return ( ``` ## Test the Configuration 1. Reload Nginx: `sudo nginx -t && sudo systemctl reload nginx` 2. Verify the script loads: `curl -I https://yourdomain.com/js/script.js` 3. Verify the event endpoint: `curl -X POST https://yourdomain.com/api/event -H "Content-Type: application/json" -d '{"test": true}'` 4. Check your site in a browser with `data-debug="true"` and confirm events are sent through the proxy --- URL: https://engagetrack.net/docs/proxy/express.md --- title: Express.js Proxy description: Set up an EngageTrack proxy with Express.js middleware. order: 4 --- # Express.js Proxy Use `http-proxy-middleware` to proxy EngageTrack requests through your Express.js server. ## Install Dependencies ```bash npm install http-proxy-middleware ``` ## Route Configuration ```javascript const express = require("express"); const { createProxyMiddleware } = require("http-proxy-middleware"); const app = express(); // Proxy the SDK script app.use( "/js/script.js", createProxyMiddleware({ target: "https://cdn.engagetrack.net", changeOrigin: true, pathRewrite: { "^/js/script.js": "/sdk.js" }, }) ); // Proxy the event API endpoint app.use( "/api/event", createProxyMiddleware({ target: "https://api.engagetrack.net", changeOrigin: true, pathRewrite: { "^/api/event": "/api/v1/event" }, onProxyReq: (proxyReq, req) => { // Forward the real client IP for geolocation const clientIp = req.headers["x-forwarded-for"] || req.socket.remoteAddress; if (clientIp) { proxyReq.setHeader("X-Forwarded-For", clientIp); } }, }) ); // ... your other routes ... app.listen(3000, () => { console.log("Server running on port 3000"); }); ``` ## TypeScript Version ```typescript import express from "express"; import { createProxyMiddleware } from "http-proxy-middleware"; const app = express(); app.use( "/js/script.js", createProxyMiddleware({ target: "https://cdn.engagetrack.net", changeOrigin: true, pathRewrite: { "^/js/script.js": "/sdk.js" }, }) ); app.use( "/api/event", createProxyMiddleware({ target: "https://api.engagetrack.net", changeOrigin: true, pathRewrite: { "^/api/event": "/api/v1/event" }, onProxyReq: (proxyReq, req) => { const clientIp = req.headers["x-forwarded-for"] || req.socket.remoteAddress; if (clientIp) { proxyReq.setHeader("X-Forwarded-For", String(clientIp)); } }, }) ); app.listen(3000); ``` The `changeOrigin: true` option sets the `Host` header to the target hostname, which is required for the upstream server to route the request correctly. ## Without http-proxy-middleware If you prefer not to add a dependency, use Node's built-in `fetch` (Node 18+): ```javascript const express = require("express"); const app = express(); app.use(express.raw({ type: "application/json", limit: "1mb" })); // Proxy the SDK script app.get("/js/script.js", async (req, res) => { const response = await fetch("https://cdn.engagetrack.net/sdk.js"); res.set("Content-Type", "application/javascript"); res.set("Cache-Control", "public, max-age=3600"); const body = await response.text(); res.send(body); }); // Proxy the event endpoint app.post("/api/event", async (req, res) => { const clientIp = req.headers["x-forwarded-for"] || req.socket.remoteAddress; const response = await fetch("https://api.engagetrack.net/api/v1/event", { method: "POST", headers: { "Content-Type": "application/json", "X-Forwarded-For": clientIp || "", }, body: req.body, }); res.status(response.status).send(await response.text()); }); app.listen(3000); ``` Always forward the `X-Forwarded-For` header with the client's real IP address. Without it, all visitors will be geolocated to your server's location. ## Updated Script Tag ```html ``` --- URL: https://engagetrack.net/docs/integrations/github.md --- title: GitHub Integration description: Connect GitHub for deploy annotations on your analytics charts. order: 1 --- # GitHub Integration EngageTrack integrates with GitHub to annotate your analytics charts with deployment markers, so you can correlate traffic changes with code releases. ## Connecting GitHub 1. Navigate to **Site Settings → Integrations → GitHub** 2. Click **Connect GitHub** 3. Authorize EngageTrack via OAuth 4. Select a repository to link GitHub OAuth connects your GitHub account for the integration feature. It does not replace your regular EngageTrack login. ## How It Works When a repository is linked, EngageTrack: 1. Listens for push events on your default branch 2. Creates an annotation for each deployment with the commit message, author, and timestamp 3. Displays deploy markers directly on the analytics time-series chart This lets you immediately see how a deployment affected your traffic, conversions, or bounce rate. ## Importing Recent Commits When you first link a repository, you can import recent commits to backfill deployment markers on your existing charts. ## Unlinking To disconnect the GitHub integration, go to **Site Settings → Integrations → GitHub** and click **Disconnect**. Existing annotations remain visible after unlinking. ## Required Permissions - **Viewing** the integration status: Viewer role or higher - **Connecting, importing, unlinking**: Admin role or higher --- URL: https://engagetrack.net/docs/integrations/revenue-providers.md --- title: Revenue Providers description: Connect Stripe, Lemon Squeezy, Paddle, or Polar for automatic revenue attribution. order: 2 --- # Revenue Provider Integrations EngageTrack connects to your payment provider to automatically attribute revenue to traffic sources. This powers the Revenue dashboard, showing exactly which channels drive real business results. ## Supported Providers - **Stripe** - **Lemon Squeezy** - **Paddle** - **Polar** ## Connecting a Provider 1. Navigate to **Site Settings → Revenue** 2. Select your payment provider 3. Authenticate: - **Stripe** — click **Connect with Stripe** to complete the OAuth flow (~30 seconds; no API key needed) - **Lemon Squeezy, Paddle, Polar** — enter your API key (and store/org ID where required) 4. Select your reporting currency 5. Click **Connect** During connection, EngageTrack validates your credentials and automatically registers a webhook on the provider. No manual webhook setup is required. API keys are encrypted at rest and are never displayed in the dashboard after initial setup. ## Revenue Attribution Once connected, here's how attribution works: 1. A visitor lands on your site → EngageTrack records their identity and traffic source 2. The visitor makes a purchase → your payment provider sends EngageTrack a webhook 3. EngageTrack matches the payment to the visitor and attributes the revenue to the original traffic source Revenue is attributed using both **first-touch** (the source that originally brought the visitor) and **last-touch** (the most recent source before purchase) models. ### Linking Visitors to Payments For accurate attribution, pass the EngageTrack visitor ID to your payment provider. For example, with Stripe: ```javascript const session = await stripe.checkout.sessions.create({ metadata: { engagetrack_visitor_id: visitorId, // from engagetrack.getVisitorId() }, // ...other options }); ``` ## Changing Currency You can update your reporting currency at any time from **Site Settings → Revenue**. Revenue from different currencies is automatically converted to your reporting currency using daily exchange rates. ## Disconnecting To disconnect your revenue provider, go to **Site Settings → Revenue** and click **Disconnect**. Existing revenue data is preserved. ## Required Permissions - **Viewing** revenue data: Viewer role or higher - **Connecting, updating, disconnecting**: Admin role or higher --- URL: https://engagetrack.net/docs/frontend/dashboard.md --- title: Dashboard Guide description: Navigating the EngageTrack dashboard — sites, settings, and analytics views. order: 1 --- # Dashboard Guide The EngageTrack dashboard is the main interface for viewing your analytics. It's available at `/dashboard` after logging in. ## Site List After login, you'll see all sites belonging to your current organization. Each card shows: - **Domain** and site name - **Status** — whether the tracking script is verified - Quick stats (if data is available) Click a site to open its analytics dashboard. ## Creating a Site 1. Click **Add Site** from the dashboard 2. Enter the site domain (e.g., `mysite.com`) and a display name 3. Copy the tracking snippet and add it to your website's `` tag ```html ``` Once the script is installed and a pageview is detected, the site card updates to show **Tracking verified**. ## Dashboard Tabs The analytics dashboard for each site includes: | Tab | Content | | --------------- | ------------------------------------------------------ | | **Overview** | KPI cards, time-series chart, all breakdown panels | | **Goals** | Conversion goals with completion counts and rates | | **Funnels** | Multi-step conversion funnel visualizations | | **Visitors** | Individual visitor profiles and event timelines | | **Revenue** | Revenue attribution by source with first/last-touch | ## Organization Settings Navigate to **Settings** (from the sidebar) to manage: - **General** — Organization name, slug - **Branding** — White-label logo, color, and custom domain (Agency plan only) - **Team** — Invite members, manage roles, transfer ownership - **Billing** — Subscription plan, payment methods, invoices, usage - **Danger Zone** — Delete the organization ## Site Settings From any site's dashboard, click the gear icon to access: - **General** — Site name, domain - **Tracking** — Toggle outbound links, file downloads, phone clicks, form submissions, custom events, localhost tracking - **Exclusions** — Exclude specific IPs and page paths from tracking - **Timezone** — Set the reporting timezone - **Public Dashboard** — Enable/disable the public-facing dashboard with granular control over which sections are visible - **Integrations** — Connect GitHub for deploy annotations, connect revenue providers - **Danger Zone** — Delete the site --- URL: https://engagetrack.net/docs/frontend/public-dashboards.md --- title: Public Dashboards description: Share your analytics publicly with a customizable, read-only dashboard. order: 2 --- # Public Dashboards EngageTrack lets you share a read-only version of your analytics with anyone — no login required. ## Enabling 1. Go to **Site Settings → Public Dashboard** 2. Toggle **Enable public dashboard** 3. Copy the shareable URL and send it to anyone ## Visibility Controls You have granular control over what visitors to your public dashboard can see. Each section can be independently toggled: | Toggle | Controls | | ------------------- | ---------------------- | | **Visitors** | Unique visitors KPI | | **Pageviews** | Pageviews KPI | | **Bounce Rate** | Bounce rate KPI | | **Session Duration**| Session duration KPI | | **Realtime** | Online visitor count | | **Chart** | Time-series chart | | **Sources** | Sources breakdown | | **Locations** | Location breakdown | | **Pages** | Pages breakdown | | **Devices** | Devices breakdown | Each toggle independently controls a section. Disabled sections are completely hidden from the public dashboard. ## Limitations - Revenue data is never exposed on public dashboards - Individual visitor profiles are not available publicly - Data is capped to the last 12 months Public dashboards are intended for transparency, not confidentiality. Anyone with the link can view the enabled metrics. Don't enable them if your traffic data is sensitive. --- URL: https://engagetrack.net/docs/billing/plans.md --- title: Plans & Pricing description: Understand EngageTrack's subscription plans, features, and usage limits. order: 1 --- # Plans & Pricing EngageTrack offers three subscription plans. Each plan defines event limits, site limits, data retention, team size, and feature access. ## Plans at a Glance | | **Maker** | **Startup** | **Agency** | | --- | --- | --- | --- | | **Price** | €5/mo | €20/mo | €50/mo | | **Events / month** | 10,000 | 200,000 | 2,000,000 | | **Sites** | 3 | 10 | Unlimited | | **Team members** | 3 | 10 | Unlimited | | **Data retention** | 12 months | 24 months | 36 months | | **Email Reports** | ✓ | ✓ | ✓ | | **CSV Export** | — | ✓ | ✓ | | **API Access** | — | ✓ | ✓ | | **White Label** | — | — | ✓ | | **Custom Domain** | — | — | ✓ | | **Priority Support** | — | — | ✓ | Yearly billing is available on all plans at a discounted rate. Visit the [pricing page](/) for current yearly prices. ## Feature Notes - **Events** — An event is any tracked interaction: pageview, custom event, outbound click, form submission, etc. - **API Access** — Programmatic access to your analytics data via REST API with scoped API keys (Startup and above). - **White Label** — Replace EngageTrack branding with your own logo and colors across the dashboard (Agency only). - **Custom Domain** — Proxy the tracking script through your own domain to improve ad blocker bypass rates (Agency only). ## Free Trial New organizations start with a **14-day free trial**. During the trial: - All features are available - No payment method is required - You'll receive email reminders before the trial ends Once the trial expires, you'll need to subscribe to a paid plan to continue using EngageTrack. ## Billing Cycle Plans are available in **monthly** or **yearly** billing cycles. Yearly plans offer a discount compared to paying monthly. --- URL: https://engagetrack.net/docs/billing/subscription-management.md --- title: Subscription Management description: Subscribe, upgrade, downgrade, cancel, and manage your billing. order: 2 --- # Subscription Management All billing actions are managed from **Organization Settings → Billing** and require the **Owner** role. ## Subscribing After your free trial, subscribe to a plan: 1. Go to **Settings → Billing** 2. Select a plan and billing cycle (monthly or yearly) 3. Enter your payment details 4. Optionally apply a coupon code 5. Confirm your subscription Email verification is required before subscribing. Verify your email from **Settings → Account** if you haven't already. ## Upgrading or Downgrading You can change your plan at any time from the Billing page. When you upgrade, you'll be charged the prorated difference immediately. When you downgrade, you receive credit toward future invoices. Before switching, you can preview the exact amount you'll be charged or credited. ## Canceling Cancel your subscription from the Billing page. After cancellation: - Your subscription remains active until the end of the current billing period - All your data is retained - You can reactivate at any time before the period ends ## Reactivating If you cancel but change your mind before the period ends, simply click **Reactivate** from the Billing page. Your subscription continues without interruption. ## Payment Methods - **Update card** — Add a new card and set it as default from the Billing page - **Remove card** — Remove an old payment method (you cannot remove your last active card on a paid plan) ## Billing Profile Update your invoicing address and tax information (company name, address, VAT/tax ID) from **Settings → Billing → Billing Profile**. This information appears on your invoices. ## Invoices View and download all past invoices from the Billing page. For advanced billing management, use the **Stripe Customer Portal** link to access your full invoice history. ## Usage Track your current pageview usage and see how much of your plan limit you've consumed from the Billing page. The counter resets at the start of each billing cycle. --- URL: https://engagetrack.net/docs/team/invitations.md --- title: Team Invitations description: Invite team members and manage roles with EngageTrack's RBAC system. order: 1 --- # Team Invitations EngageTrack supports multi-user teams with four permission tiers. Invite your colleagues and control exactly what they can see and do. ## Roles | Role | Permissions | | ---------- | ----------------------------------------------------- | | **Owner** | Full access — billing, team management, site deletion | | **Admin** | Manage team members, sites, and settings (no billing) | | **Member** | View analytics for assigned sites, manage goals and funnels | | **Viewer** | Read-only access to analytics dashboards | ## Sending an Invitation 1. Navigate to **Settings → Team** 2. Click **Invite Member** 3. Enter the person's email address 4. Select a role 5. Optionally restrict access to specific sites ``` POST /api/v1/organizations/:orgId/team/invites { "email": "teammate@company.com", "role": "member", "site_ids": ["site-uuid-1", "site-uuid-2"] // optional } ``` Invitations expire after **7 days**. The invitee will receive an email with a link to accept. ## Per-Site Access Control For larger teams, you can restrict members to specific sites: - **Owners** and **Admins** always have access to all sites - **Members** and **Viewers** can be scoped to individual sites - Access is managed in **Settings → Team → Edit Member** ## Ownership Transfer Organization owners can transfer ownership to another admin: 1. Go to **Settings → Team** 2. Click the menu icon next to the target admin 3. Select **Transfer Ownership** Ownership transfer is irreversible. You will be demoted to Admin role. --- URL: https://engagetrack.net/docs/team/roles.md --- title: Roles & Permissions description: Understand the four permission tiers in EngageTrack's role-based access control system. order: 2 --- # Roles & Permissions EngageTrack uses a four-tier role system to manage what each team member can do within an organization. ## Role Hierarchy | Role | Description | | ---------- | ----------------------------------------------------- | | **Owner** | Full control — billing, team management, site deletion | | **Admin** | Manage team, sites, and settings (no billing access) | | **Member** | View analytics and manage goals, funnels, and annotations | | **Viewer** | Read-only access to analytics dashboards | ## Permission Matrix | Action | Owner | Admin | Member | Viewer | | ------------------------------- | ----- | ----- | ------ | ------ | | View analytics | ✅ | ✅ | ✅ | ✅ | | View goals & funnel stats | ✅ | ✅ | ✅ | ✅ | | Edit/archive goals | ✅ | ✅ | ✅ | ❌ | | Create/edit/delete funnels | ✅ | ✅ | ✅ | ❌ | | Create/delete annotations | ✅ | ✅ | ✅ | ❌ | | Create/edit/delete sites | ✅ | ✅ | ❌ | ❌ | | Update site settings | ✅ | ✅ | ❌ | ❌ | | Update organization settings | ✅ | ✅ | ❌ | ❌ | | Connect integrations | ✅ | ✅ | ❌ | ❌ | | Invite/remove team members | ✅ | ✅ | ❌ | ❌ | | Change member roles | ✅ | ✅ | ❌ | ❌ | | Manage site access per member | ✅ | ✅ | ❌ | ❌ | | Manage billing & subscription | ✅ | ❌ | ❌ | ❌ | | Transfer ownership | ✅ | ❌ | ❌ | ❌ | | Delete organization | ✅ | ❌ | ❌ | ❌ | ## Email Verification Certain actions require a verified email address: - Subscribing to a paid plan - Sending team invitations ## Changing Roles Admins and owners can change any member's role from the **Team** settings page. An organization must always have exactly one owner. To change the owner, use the ownership transfer feature instead. ## Leaving an Organization Any member (except the owner) can leave an organization from the **Team** settings page. ## Ownership Transfer The owner can transfer ownership to any admin from **Settings → Team → Transfer Ownership**. After transfer, the original owner is demoted to the Admin role. This action is **irreversible**. --- URL: https://engagetrack.net/docs/team/site-access.md --- title: Site Access Control description: Restrict team members to specific sites within your organization. order: 3 --- # Site Access Control For organizations with multiple sites, you can restrict which sites specific team members can access. ## How It Works - **Owners** and **Admins** always have access to all sites — they cannot be restricted - **Members** and **Viewers** can be scoped to specific sites - By default, all members can see all sites (no restrictions) - Once you assign specific sites to a member, they can only see those sites ## Managing Site Access 1. Go to **Settings → Team** 2. Click on a team member 3. Under **Site Access**, select which sites they should be able to view 4. Save the changes To restore full access, remove all site restrictions for that member. ## Behavior When a member has site restrictions: - The **dashboard** only shows their assigned sites - **Analytics data** only covers their assigned sites - **Goals, funnels, and visitors** are scoped to accessible sites only ## Example Imagine you have an agency with three client sites: | Site | Marketing Team | Design Team | | --------------- | -------------- | ----------- | | client-a.com | ✅ | ✅ | | client-b.com | ✅ | ❌ | | client-c.com | ❌ | ✅ | Each team's members would only see the sites they're assigned to. ## Permissions Only **Admin** and **Owner** roles can view and modify site access assignments. Site access restrictions only apply to Members and Viewers. Admins and Owners always see all sites. --- URL: https://engagetrack.net/docs/api/authentication.md --- title: API Authentication description: Authenticate with the EngageTrack API using API keys. order: 1 --- # API Authentication All EngageTrack API requests are authenticated using **API keys**. API keys provide scoped, long-lived access and are designed for server-side integrations, CI/CD pipelines, data warehouses, and automation workflows. ## Getting an API Key 1. Navigate to **Settings > API Keys** in your dashboard 2. Click **Create API Key** 3. Enter a descriptive name (e.g., `Data Warehouse Sync`) 4. Select the [scopes](/docs/api/api-keys#scope-reference) your integration needs 5. Optionally set an expiration date 6. Click **Create** and copy the key immediately The full API key is shown **only once** at creation. Copy it and store it securely — in a secrets manager or environment variable. If you lose it, you must revoke the key and create a new one. API keys require a **Startup plan** or higher. See [Plans & Pricing](/docs/billing/plans) for details. ## Using an API Key Pass the key as a Bearer token in the `Authorization` header of every request: ```bash curl https://api.engagetrack.net/api/v1/organizations/{orgId}/sites \ -H "Authorization: Bearer et_live_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6" ``` ## Key Format API keys follow the format `et_live_` followed by 32 hexadecimal characters: ``` et_live_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6 ``` ## Scopes API keys are granted specific scopes that control which endpoints they can access. Assign only the scopes your integration needs. | Resource | Scope | Grants access to | | --- | --- | --- | | **Analytics** | `analytics:read` | Stats, charts, pages, sources, devices, locations, revenue, channels | | **Sites** | `sites:read` | List sites and get site details | | **Goals** | `goals:read` | List goals, goal stats, and goal completions | | **Goals** | `goals:write` | Update and archive/unarchive goals | | **Funnels** | `funnels:read` | List funnels and view funnel analysis | | **Funnels** | `funnels:write` | Create, update, and delete funnels | | **Annotations** | `annotations:read` | List annotations | | **Annotations** | `annotations:write` | Create and delete annotations | | **Visitors** | `visitors:read` | List visitors and view visitor timelines | Write scopes do not imply read access. If your integration needs to both read and write goals, assign both `goals:read` and `goals:write`. ## Limits - Maximum **10 API keys** per organization - API keys grant access to **data endpoints only** (analytics, goals, funnels, annotations, visitors, sites) - API keys **cannot** access management endpoints (billing, team, integrations) - Rate limits apply per-key — see [Rate Limiting](/docs/api-reference/overview#rate-limiting) ## Expiration API keys can have an optional expiration date. Expired keys return `401 Unauthorized`. We recommend setting an expiration and rotating keys periodically. ## Security Best Practices - **Use minimal scopes.** Only assign what your integration actually needs. - **Set an expiration date.** Avoid keys that live forever. Rotate before expiry. - **Store keys securely.** Use environment variables or a secrets manager. Never commit API keys to version control or embed them in client-side code. - **One key per integration.** If one integration is compromised, you can revoke it without affecting others. ## Error Responses ### 401 Unauthorized ```json { "error": "Invalid or expired API key" } ``` The key does not exist, has been revoked, or has expired. ### 402 Payment Required ```json { "error": "API key access requires a Startup plan or higher" } ``` Upgrade your plan at **Settings > Billing**. ### 403 Forbidden ```json { "error": "API key missing required scope: analytics:read" } ``` The key lacks the scope needed for this endpoint. Create a new key with the correct scopes. --- For full key management (creating, listing, and revoking keys) see the [API Keys guide](/docs/api/api-keys). --- URL: https://engagetrack.net/docs/api/api-keys.md --- title: API Keys description: Create and manage API keys for programmatic access to your analytics data. order: 2 --- # API Keys API keys let you access EngageTrack data programmatically without a user session. They are ideal for server-side integrations, automated reporting, data warehouse syncs, and CI/CD pipelines. API keys require a **Startup plan** or higher. Organizations on the Maker plan will receive a `402` error when attempting to create a key. ## Creating an API Key ### Via the Dashboard 1. Go to **Settings > API Keys** 2. Click **Create API Key** 3. Enter a name and select scopes 4. Click **Create** and copy the key immediately The full key is shown **only once**. Store it in a secure location such as a secrets manager or environment variable. If you lose it, you must revoke the key and create a new one. ### Via the API You can also create API keys programmatically. Key management endpoints require a user session token — obtain one by logging in via the dashboard or the `/api/v1/auth/login` endpoint. ```bash curl -X POST \ 'https://api.engagetrack.net/api/v1/organizations/{orgId}/api-keys' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ -d '{ "name": "Data Warehouse Sync", "scopes": ["analytics:read", "sites:read"], "expires_at": "2026-12-31T23:59:59Z" }' ``` The response includes the full key in the `key` field. This is the only time the full key is returned. ## Scope Reference Scopes control which API endpoints a key can access. Assign only the scopes your integration needs. | Resource | Scope | Grants access to | | --- | --- | --- | | **Analytics** | `analytics:read` | Stats, charts, pages, sources, devices, locations, revenue, channels, and all other analytics breakdowns | | **Sites** | `sites:read` | List sites and get site details | | **Goals** | `goals:read` | List goals, goal stats, and goal completions | | **Goals** | `goals:write` | Update and archive/unarchive goals | | **Funnels** | `funnels:read` | List funnels and view funnel analysis | | **Funnels** | `funnels:write` | Create, update, and delete funnels | | **Annotations** | `annotations:read` | List annotations | | **Annotations** | `annotations:write` | Create and delete annotations | | **Visitors** | `visitors:read` | List visitors and view visitor timelines | Write scopes do not imply read access. If your integration needs to both read and write goals, assign both `goals:read` and `goals:write`. ## Usage Examples All examples use the base URL `https://api.engagetrack.net/api/v1`. ### Get site analytics stats ```bash curl -X GET \ 'https://api.engagetrack.net/api/v1/organizations/{orgId}/sites/{siteId}/analytics/stats?period=30d' \ -H 'Authorization: Bearer et_live_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6' ``` **Required scope:** `analytics:read` ### List all sites ```bash curl -X GET \ 'https://api.engagetrack.net/api/v1/organizations/{orgId}/sites' \ -H 'Authorization: Bearer et_live_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6' ``` **Required scope:** `sites:read` ### Export page analytics ```bash curl -X GET \ 'https://api.engagetrack.net/api/v1/organizations/{orgId}/sites/{siteId}/analytics/pages?period=30d&limit=100' \ -H 'Authorization: Bearer et_live_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6' ``` **Required scope:** `analytics:read` ### List visitors ```bash curl -X GET \ 'https://api.engagetrack.net/api/v1/organizations/{orgId}/sites/{siteId}/visitors?page=1&limit=50' \ -H 'Authorization: Bearer et_live_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6' ``` **Required scope:** `visitors:read` ## Security Best Practices - **Use minimal scopes.** Only assign the scopes your integration actually needs. A reporting dashboard only needs `analytics:read` and `sites:read`. - **Set an expiration date.** Avoid creating keys that live forever. Set a reasonable expiration (e.g., 90 days) and rotate before it expires. - **Store keys securely.** Use environment variables or a secrets manager. Never commit API keys to version control or embed them in client-side code. - **Rotate keys regularly.** Create a new key, update your integration, then revoke the old key. This limits the impact of a leaked key. - **Use one key per integration.** If one integration is compromised, you can revoke its key without affecting others. - **Monitor usage.** Review your active API keys periodically in **Settings > API Keys** and revoke any that are no longer in use. ## Rate Limits API key requests are rate-limited per key. Analytics endpoints allow up to **600 requests per minute**. If you exceed the limit, the API returns `429 Too Many Requests` with `X-RateLimit-*` headers indicating when you can retry. | Header | Description | | --- | --- | | `X-RateLimit-Limit` | Maximum requests allowed in the current window | | `X-RateLimit-Remaining` | Requests remaining in the current window | | `X-RateLimit-Reset` | Unix timestamp when the window resets | ## Error Responses ### 401 Unauthorized — Invalid or expired key ```json { "error": "Invalid or expired API key" } ``` The key does not exist, has been revoked, or has expired. Create a new key if needed. ### 402 Payment Required — Subscription required ```json { "error": "API key access requires a Startup plan or higher" } ``` Your organization is on the Maker plan, which does not include API access. Upgrade to Startup or Agency at **Settings > Billing**. ### 403 Forbidden — Missing scope ```json { "error": "API key missing required scope: analytics:read" } ``` The key does not have the scope needed for the requested endpoint. Create a new key with the correct scopes. ### 429 Too Many Requests — Rate limited ```json { "error": "Rate limit exceeded. Retry after 2026-03-14T12:01:00Z" } ``` Back off and retry after the time indicated in the `X-RateLimit-Reset` header. ## Managing API Keys ### Listing Keys View all active API keys in **Settings > API Keys**, or via the API (requires session token): ```bash curl -X GET \ 'https://api.engagetrack.net/api/v1/organizations/{orgId}/api-keys' \ -H 'Authorization: Bearer ' ``` The list shows each key's name, scopes, creation date, expiration, and a masked preview of the key (last 4 characters only). ### Revoking a Key Revoke a key from the dashboard by clicking the **Revoke** button, or via the API (requires session token): ```bash curl -X DELETE \ 'https://api.engagetrack.net/api/v1/organizations/{orgId}/api-keys/{keyId}' \ -H 'Authorization: Bearer ' ``` Revoked keys stop working immediately. This action cannot be undone. --- URL: https://engagetrack.net/docs/api-reference/overview.md --- title: API Reference description: Complete REST API reference for EngageTrack. order: 1 --- # API Reference All API endpoints are served under `/api/v1` and require authentication via the `Authorization` header unless otherwise noted. ## Base URL ``` https://api.engagetrack.net/api/v1 ``` ## Authentication All API requests are authenticated using **API keys**. Pass the key as a Bearer token in the `Authorization` header: ```bash curl -H "Authorization: Bearer et_live_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6" \ https://api.engagetrack.net/api/v1/organizations/{orgId}/sites ``` API keys provide scoped access to data endpoints (analytics, goals, funnels, annotations, visitors, sites). Create and manage keys in **Settings > API Keys**. See the [Authentication guide](/docs/api/authentication) for full details. ## Response Format All successful responses are wrapped in a standard envelope: ```json { "success": true, "data": { ... } } ``` Error responses use: ```json { "error": "Error message" } ``` ## Common Query Parameters Most analytics endpoints accept these filters: | Parameter | Type | Description | | --------- | -------- | --------------------------------------------- | | `period` | `string` | `day`, `7d`, `30d`, `month`, `12mo`, `custom` | | `date` | `string` | ISO date – base date for the period | | `from` | `string` | Start date for custom range | | `to` | `string` | End date for custom range | | `filters` | `string` | JSON-encoded filter array | ## HTTP Status Codes | Code | Meaning | | ----- | --------------------- | | `200` | Success | | `201` | Created | | `202` | Accepted | | `400` | Bad Request | | `401` | Unauthorized | | `403` | Forbidden | | `404` | Not Found | | `429` | Rate Limited | | `500` | Internal Server Error | ## Rate Limiting Endpoints are rate-limited per IP/user. Auth endpoints have stricter limits (5-50 req/window). Analytics endpoints are more generous. Responses include `X-RateLimit-*` headers. Browse the sidebar to explore endpoints grouped by resource. --- URL: https://engagetrack.net/docs/api-reference/get-attribution.md --- title: Attribution description: Get revenue attribution data by source and model. order: 38 method: GET --- # Attribution Returns revenue attribution data broken down by source, using the specified attribution model. ## Endpoint ``` GET /api/v1/organizations/:orgId/sites/:siteId/analytics/attribution ``` ## Query Parameters | Parameter | Type | Required | Description | | --------- | -------- | -------- | ----------------------------------------------------------- | | `period` | `string` | No | Time period (`day`, `7d`, `30d`, `month`, `12mo`, `custom`) | | `model` | `string` | No | Attribution model: `first_touch` or `last_touch` (default: `last_touch`) | | `groupBy` | `string` | No | Group results by: `source`, `medium`, or `campaign` (default: `source`) | ## Response fields Returns an array of attribution entries: | Field | Type | Description | | ------------- | -------- | ---------------------------------------- | | `group` | `string` | Group value (source, medium, or campaign name) | | `conversions` | `number` | Number of conversions attributed | | `revenue` | `number` | Attributed revenue | --- URL: https://engagetrack.net/docs/api-reference/get-campaigns.md --- title: Campaigns description: Get campaign breakdown with visitor and revenue data. order: 36 method: GET --- # Campaigns Returns a breakdown of traffic by UTM campaign, ranked by visitor count. ## Endpoint ``` GET /api/v1/organizations/:orgId/sites/:siteId/analytics/campaigns ``` ## Query Parameters | Parameter | Type | Required | Description | | --------- | -------- | -------- | ----------------------------------------------------------- | | `period` | `string` | No | Time period (`day`, `7d`, `30d`, `month`, `12mo`, `custom`) | | `limit` | `number` | No | Maximum number of results (default: 10) | | `filters` | `string` | No | JSON-encoded filter array | ## Response fields Returns an array of campaign entries: | Field | Type | Description | | ---------- | -------- | ------------------------------------ | | `campaign` | `string` | UTM campaign name | | `visitors` | `number` | Unique visitors from this campaign | --- URL: https://engagetrack.net/docs/api-reference/get-channels.md --- title: Channels description: Get enriched channel breakdown with UTM parameters for a site. order: 35 method: GET --- # Channels Returns enriched channel data combining UTM parameters with referrer information, ranked by visitor count. ## Endpoint ``` GET /api/v1/organizations/:orgId/sites/:siteId/analytics/channels/enriched ``` ## Query Parameters | Parameter | Type | Required | Description | | --------- | -------- | -------- | ----------------------------------------------------------- | | `period` | `string` | No | Time period (`day`, `7d`, `30d`, `month`, `12mo`, `custom`) | | `limit` | `number` | No | Maximum number of results (default: 10) | | `filters` | `string` | No | JSON-encoded filter array | ## Response fields Returns a wrapped response with `channels` and `currency`: | Field | Type | Description | | ---------- | -------- | ---------------------------------- | | `channels` | `array` | Array of channel entries (see below) | | `currency` | `string` | Currency code (e.g. `USD`) | Each channel entry: | Field | Type | Description | | --------------- | -------- | ------------------------------------------------------- | | `channel` | `string` | Channel name | | `visitors` | `number` | Unique visitors from this channel | | `total_revenue` | `number` | Total revenue from this channel | | `top_sources` | `array` | Top sources within the channel (see below) | Each `top_sources` entry: | Field | Type | Description | | --------- | -------- | --------------------------------- | | `source` | `string` | Source name | | `visitors`| `number` | Unique visitors from this source | | `percent` | `number` | Percentage of channel visitors | ## Related Endpoints | Endpoint | Description | | ------------------------- | --------------------------------------------- | | `.../analytics/sources` | Traffic grouped by top-level source | | `.../analytics/referrers` | Traffic grouped by normalized referrer domain | | `.../analytics/campaigns` | Traffic grouped by UTM campaign | --- URL: https://engagetrack.net/docs/api-reference/get-devices.md --- title: Devices description: Get device, browser, or OS breakdown for a site. order: 34 method: GET --- # Devices Returns a breakdown of visitors by device type, browser, or operating system. ## Endpoint ``` GET /api/v1/organizations/:orgId/sites/:siteId/analytics/devices ``` ## Query Parameters | Parameter | Type | Required | Description | | --------- | -------- | -------- | ----------------------------------------------------------- | | `period` | `string` | No | Time period (`day`, `7d`, `30d`, `month`, `12mo`, `custom`) | | `type` | `string` | No | Breakdown type: `browser`, `os`, or `device` (default: `device`) | | `limit` | `number` | No | Maximum number of results (default: 10) | | `filters` | `string` | No | JSON-encoded filter array | ## Response fields Returns an array of device entries: | Field | Type | Description | | ---------- | -------- | -------------------------------------------- | | `name` | `string` | Device, browser, or OS name | | `count` | `number` | Unique visitors using this device/browser/OS | --- URL: https://engagetrack.net/docs/api-reference/export-csv.md --- title: Export CSV description: Export analytics data as a CSV file. order: 45 method: GET --- # Export CSV Exports analytics data as a downloadable CSV file. ## Endpoint ``` GET /api/v1/organizations/:orgId/sites/:siteId/analytics/export ``` ## Query Parameters | Parameter | Type | Required | Description | | --------- | -------- | -------- | ----------------------------------------------------------- | | `period` | `string` | No | Time period (`day`, `7d`, `30d`, `month`, `12mo`, `custom`) | | `metric` | `string` | Yes | Export type: `pageviews`, `sources`, `pages`, `devices`, `locations`, or `goals` | | `filters` | `string` | No | JSON-encoded filter array | ## Response Returns a CSV file with `Content-Type: text/csv` and a `Content-Disposition` header for download. The columns vary by export type. --- URL: https://engagetrack.net/docs/api-reference/get-chart.md --- title: Get Chart Data description: Retrieve time-series chart data for a site. order: 3 method: GET --- # Get Chart Data Returns time-series data points for rendering analytics charts. Each point includes visitors, pageviews, sessions, revenue, and order counts. ## Endpoint ``` GET /api/v1/organizations/:orgId/sites/:siteId/analytics/chart ``` ## Query Parameters | Parameter | Type | Required | Description | | --------- | -------- | -------- | ------------------------------------------ | | `period` | `string` | No | Time period | | `date` | `string` | No | Base date (ISO 8601) | | `from` | `string` | No | Start date for custom range | | `to` | `string` | No | End date for custom range | | `group` | `string` | No | Grouping: `hour` or `day` (default: `day`) | | `filters` | `string` | No | JSON-encoded filter array | ## Response fields Returns an array of data points, each containing: | Field | Type | Description | | ----------- | -------- | ------------------------- | | `timestamp` | `string` | ISO 8601 timestamp | | `visitors` | `number` | Unique visitors in bucket | | `pageviews` | `number` | Total pageviews in bucket | | `sessions` | `number` | Unique sessions in bucket | | `revenue` | `number` | Revenue in bucket | | `orders` | `number` | Order count in bucket | --- URL: https://engagetrack.net/docs/api-reference/get-stats.md --- title: Get Stats description: Retrieve aggregate analytics statistics for a site. order: 2 method: GET --- # Get Stats Returns aggregate statistics for the given time period. ## Endpoint ``` GET /api/v1/organizations/:orgId/sites/:siteId/analytics/stats ``` ## Query Parameters | Parameter | Type | Required | Description | | --------- | -------- | -------- | ----------------------------------------------------------- | | `period` | `string` | No | Time period (`day`, `7d`, `30d`, `month`, `12mo`, `custom`) | | `date` | `string` | No | Base date (ISO 8601) | | `from` | `string` | No | Start date for custom range | | `to` | `string` | No | End date for custom range | | `filters` | `string` | No | JSON-encoded filter array | ## Response fields | Field | Type | Description | | ----------------- | -------- | --------------------------------- | | `pageviews` | `number` | Total pageviews in the period | | `unique_visitors` | `number` | Unique visitors (distinct hashes) | | `sessions` | `number` | Unique sessions | --- URL: https://engagetrack.net/docs/api-reference/list-annotations.md --- title: List Annotations description: Get all annotations for a site. order: 42 method: GET --- # List Annotations Returns all annotations for a site, ordered by date. Annotations are markers on the analytics timeline (e.g. deployments, marketing launches). ## Endpoint ``` GET /api/v1/organizations/:orgId/sites/:siteId/annotations ``` ## Response fields Returns an array of annotation entries: | Field | Type | Description | | ------------- | -------- | ----------------------------------- | | `id` | `string` | Annotation ID | | `label` | `string` | Annotation label | | `occurred_at` | `string` | Annotation date (ISO 8601) | | `description` | `string` | Optional longer description | | `color` | `string` | Marker color | | `created_by` | `object` | Author object with `id`, `name`, `email` | | `created_at` | `string` | Creation timestamp (ISO 8601) | --- URL: https://engagetrack.net/docs/api-reference/list-funnels.md --- title: List Funnels description: List all funnels for a site. order: 30 method: GET --- # List Funnels Returns all funnels defined for a site, including their steps. ## Endpoint ``` GET /api/v1/organizations/:orgId/sites/:siteId/funnels ``` ## Response fields Each funnel object contains: | Field | Type | Description | | ------------- | -------- | -------------------- | | `id` | `string` | Funnel ID | | `site_id` | `string` | Site ID | | `name` | `string` | Funnel name | | `description` | `string` | Funnel description | | `steps` | `array` | Ordered funnel steps | Each step contains: | Field | Type | Description | | ------------ | -------- | ------------------------------- | | `id` | `string` | Step ID | | `name` | `string` | Step label | | `order` | `number` | Step position (1-indexed) | | `type` | `string` | `pageview` or `custom_event` | | `pattern` | `string` | Page path or event name | | `match_type` | `string` | `exact`, `contains`, or `regex` | --- URL: https://engagetrack.net/docs/api-reference/list-goals.md --- title: List Goals description: List all goals for a site. order: 20 method: GET --- # List Goals Returns all goals configured for the given site. ## Endpoint ``` GET /api/v1/organizations/:orgId/sites/:siteId/goals ``` ## Response fields Each goal object contains: | Field | Type | Description | | ------------ | -------- | -------------------------------------- | | `id` | `string` | Goal ID | | `site_id` | `string` | Site ID | | `name` | `string` | Goal display name | | `type` | `string` | `pageview` or `custom_event` | | `pattern` | `string` | Page path or event name to match | | `match_type` | `string` | `exact`, `contains`, or `regex` | | `value` | `number` | Optional monetary value per conversion | | `currency` | `string` | Optional currency code (e.g. `USD`) | ## Goal Stats To get conversion stats for all goals in a period: ``` GET /api/v1/organizations/:orgId/sites/:siteId/goals/stats ``` Returns an array of stats per goal: | Field | Type | Description | | -------------------- | -------- | ------------------------------------ | | `goal_id` | `string` | Goal ID | | `name` | `string` | Goal name | | `type` | `string` | Goal type | | `conversions` | `number` | Total conversions | | `unique_conversions` | `number` | Unique visitor conversions | | `revenue` | `number` | Total revenue from conversions | | `conversion_rate` | `number` | Percentage of visitors who converted | --- URL: https://engagetrack.net/docs/api-reference/list-sites.md --- title: List Sites description: List all sites in an organization. order: 10 method: GET --- # List Sites Returns all sites belonging to the specified organization that the authenticated user has access to. ## Endpoint ``` GET /api/v1/organizations/:orgId/sites ``` --- URL: https://engagetrack.net/docs/api-reference/list-visitors.md --- title: List Visitors description: Get a paginated list of visitors for a site. order: 40 method: GET --- # List Visitors Returns a paginated list of visitors for a site, ordered by most recently seen. ## Endpoint ``` GET /api/v1/organizations/:orgId/sites/:siteId/visitors ``` ## Query Parameters | Parameter | Type | Required | Description | | --------- | -------- | -------- | ------------------------------------------ | | `page` | `number` | No | Page number (default: 1) | | `limit` | `number` | No | Results per page (default: 50, max: 100) | | `search` | `string` | No | Search by email, name, UID, or external ID | ## Response fields Each visitor object in the `visitors` array: | Field | Type | Description | | ---------------------- | -------- | ----------------------------------- | | `id` | `string` | Visitor UUID | | `uid` | `string` | Persistent visitor UID from tracker | | `email` | `string` | Identified email (if set) | | `name` | `string` | Identified name (if set) | | `avatar_url` | `string` | Identified avatar URL (if set) | | `external_id` | `string` | Your user ID (if identified) | | `first_seen_at` | `string` | First visit timestamp | | `last_seen_at` | `string` | Most recent visit timestamp | | `total_sessions` | `number` | Lifetime session count | | `total_pageviews` | `number` | Lifetime pageview count | | `total_goals` | `number` | Lifetime goal completions | | `total_revenue` | `number` | Lifetime revenue | | `last_country` | `string` | Most recent country code | | `last_browser` | `string` | Most recent browser | | `last_os` | `string` | Most recent operating system | | `last_device` | `string` | Most recent device type | | `last_referrer_source` | `string` | Most recent traffic source | The response also includes pagination metadata: `total`, `page`, and `limit`. ## Visitor Timeline To get the event timeline for a specific visitor: ``` GET /api/v1/organizations/:orgId/sites/:siteId/visitors/:visitorId/timeline ``` Returns the visitor profile along with a paginated list of their events. --- URL: https://engagetrack.net/docs/api-reference/get-locations.md --- title: Locations description: Get geographic breakdown of visitors for a site. order: 33 method: GET --- # Locations Returns a breakdown of visitors by country, ranked by unique visitor count. ## Endpoint ``` GET /api/v1/organizations/:orgId/sites/:siteId/analytics/locations ``` ## Query Parameters | Parameter | Type | Required | Description | | --------- | -------- | -------- | ----------------------------------------------------------- | | `period` | `string` | No | Time period (`day`, `7d`, `30d`, `month`, `12mo`, `custom`) | | `type` | `string` | No | Breakdown type: `country`, `region`, or `city` (default: `country`) | | `limit` | `number` | No | Maximum number of results (default: 10) | | `filters` | `string` | No | JSON-encoded filter array | ## Response fields Returns an array of location entries: | Field | Type | Description | | ---------- | -------- | ------------------------------------ | | `location` | `string` | Location name (country code, region, or city) | | `visitors` | `number` | Unique visitors from this location | --- URL: https://engagetrack.net/docs/api-reference/get-realtime.md --- title: Realtime Stats description: Get current realtime visitor count. order: 6 method: GET --- # Realtime Stats Returns the number of visitors currently active on the site (within a 5-minute rolling window). ## Endpoint ``` GET /api/v1/organizations/:orgId/sites/:siteId/analytics/realtime ``` ## Response fields | Field | Type | Description | | ----------------- | -------- | ----------------------------------- | | `active_visitors` | `number` | Number of currently active visitors | --- URL: https://engagetrack.net/docs/api-reference/get-referrers.md --- title: Referrers description: Get referrer source breakdown with visitor and revenue data. order: 37 method: GET --- # Referrers Returns a breakdown of traffic by normalized referrer domain, ranked by visitor count. ## Endpoint ``` GET /api/v1/organizations/:orgId/sites/:siteId/analytics/referrers ``` ## Query Parameters | Parameter | Type | Required | Description | | --------- | -------- | -------- | ----------------------------------------------------------- | | `period` | `string` | No | Time period (`day`, `7d`, `30d`, `month`, `12mo`, `custom`) | | `limit` | `number` | No | Maximum number of results (default: 10) | | `filters` | `string` | No | JSON-encoded filter array | ## Response fields Returns an array of referrer entries: | Field | Type | Description | | ---------- | -------- | ------------------------------------- | | `referrer` | `string` | Normalized referrer domain | | `visitors` | `number` | Unique visitors from this referrer | --- URL: https://engagetrack.net/docs/api-reference/get-revenue-chart.md --- title: Revenue Chart description: Get time-series revenue data for charting. order: 39 method: GET --- # Revenue Chart Returns time-series revenue data suitable for charting, grouped by the specified interval. ## Endpoint ``` GET /api/v1/organizations/:orgId/sites/:siteId/analytics/revenue-chart ``` ## Query Parameters | Parameter | Type | Required | Description | | --------- | -------- | -------- | ----------------------------------------------------------- | | `period` | `string` | No | Time period (`day`, `7d`, `30d`, `month`, `12mo`, `custom`) | | `group` | `string` | No | Grouping interval: `hour` or `day` (default: `day`) | | `filters` | `string` | No | JSON-encoded filter array | ## Response fields Returns an array of time-series data points: | Field | Type | Description | | ----------- | -------- | ------------------------------- | | `timestamp` | `string` | ISO 8601 timestamp for the bucket | | `revenue` | `number` | Total revenue in the period | | `orders` | `number` | Number of orders in the period | | `customers` | `number` | Distinct paying visitors in the period | --- URL: https://engagetrack.net/docs/api-reference/get-revenue.md --- title: Revenue Overview description: Get revenue attribution analytics and overview. order: 7 method: GET --- # Revenue Overview Returns revenue metrics including total revenue, order count, customer count, average order value, and breakdowns by source, campaign, country, and page. ## Endpoint ``` GET /api/v1/organizations/:orgId/sites/:siteId/analytics/revenue-overview ``` ## Query Parameters | Parameter | Type | Required | Description | | --------- | -------- | -------- | ------------------------- | | `period` | `string` | No | Time period | | `date` | `string` | No | Base date | | `filters` | `string` | No | JSON-encoded filter array | ## Response fields | Field | Type | Description | | ----------------- | -------- | ----------------------------------- | | `total_revenue` | `number` | Total revenue in the period | | `order_count` | `number` | Number of purchase events | | `customers` | `number` | Distinct paying visitors | | `avg_order_value` | `number` | Average revenue per order | | `by_source` | `array` | Revenue breakdown by traffic source | | `by_campaign` | `array` | Revenue breakdown by UTM campaign | | `by_country` | `array` | Revenue breakdown by country | | `by_page` | `array` | Revenue breakdown by landing page | ## Revenue Chart For time-series revenue data, use: ``` GET /api/v1/organizations/:orgId/sites/:siteId/analytics/revenue-chart ``` Returns an array of `{timestamp, revenue, orders, customers}` data points. --- URL: https://engagetrack.net/docs/api-reference/team-members.md --- title: Team Members description: List and manage team members in an organization. order: 50 method: GET --- # Team Members Returns all members of the specified organization. ## Endpoint ``` GET /api/v1/organizations/:orgId/team/members ``` --- URL: https://engagetrack.net/docs/api-reference/get-pages.md --- title: Top Pages description: Get top, entry, and exit pages for a site. order: 4 method: GET --- # Top Pages Returns a breakdown of page paths by pageview count and unique visitors. Supports top pages, entry pages, and exit pages. ## Endpoint ``` GET /api/v1/organizations/:orgId/sites/:siteId/analytics/pages ``` ## Query Parameters | Parameter | Type | Required | Description | | --------- | -------- | -------- | ------------------------------------- | | `period` | `string` | No | Time period | | `type` | `string` | No | `pages` (default), `entry`, or `exit` | | `limit` | `number` | No | Max results to return (default: 10) | | `filters` | `string` | No | JSON-encoded filter array | ## Response fields Returns an array of page entries: | Field | Type | Description | | ----------- | -------- | ------------------------------------ | | `page_path` | `string` | The page URL path (e.g., `/pricing`) | | `views` | `number` | Total pageview count | | `visitors` | `number` | Unique visitors for this page | --- URL: https://engagetrack.net/docs/api-reference/get-sources.md --- title: Top Sources description: Get traffic sources breakdown for a site. order: 5 method: GET --- # Top Sources Returns the top traffic sources (referrer domains) ranked by unique visitors. ## Endpoint ``` GET /api/v1/organizations/:orgId/sites/:siteId/analytics/sources ``` ## Query Parameters | Parameter | Type | Required | Description | | --------- | -------- | -------- | ------------------------- | | `period` | `string` | No | Time period | | `limit` | `number` | No | Max results (default: 10) | | `filters` | `string` | No | JSON-encoded filter array | ## Response fields Returns an array of source entries: | Field | Type | Description | | ---------- | -------- | -------------------------------- | | `source` | `string` | Referrer source name | | `visitors` | `number` | Unique visitors from this source | ## Related Endpoints | Endpoint | Description | | ------------------------- | ---------------------------------------------------- | | `.../analytics/channels` | Traffic grouped by channel (UTM > referrer > Direct) | | `.../analytics/referrers` | Traffic grouped by normalized referrer domain | | `.../analytics/campaigns` | Traffic grouped by UTM campaign | --- URL: https://engagetrack.net/docs/api-reference/get-visitor-timeline.md --- title: Visitor Timeline description: Get the chronological event timeline for a specific visitor. order: 41 method: GET --- # Visitor Timeline Returns a chronological feed of events for a specific visitor, including pageviews, goal completions, and purchases. ## Endpoint ``` GET /api/v1/organizations/:orgId/sites/:siteId/visitors/:visitorId/timeline ``` ## Path Parameters | Parameter | Type | Required | Description | | ----------- | -------- | -------- | -------------- | | `visitorId` | `string` | Yes | The visitor ID | ## Response fields Returns the visitor profile and a `timeline` array. The response includes pagination fields `total`, `page`, and `limit`. Each timeline entry: | Field | Type | Description | | ------------------ | -------- | -------------------------------------------------- | | `id` | `string` | Event ID | | `session_id` | `string` | Session ID | | `event_type` | `string` | Event type (`pageview`, `goal`, `purchase`, `form`) | | `timestamp` | `string` | ISO 8601 event timestamp | | `page_url` | `string` | Page URL (for pageviews) | | `page_title` | `string` | Page title (for pageviews) | | `event_name` | `string` | Event/goal name (for goal events) | | `revenue` | `number` | Revenue amount (for purchase events) | | `currency` | `string` | Revenue currency code | | `referrer_source` | `string` | Referrer source for this event | | `properties` | `object` | Custom event properties | --- URL: https://engagetrack.net/docs/api-reference/delete-goal.md --- title: Archive Goal description: Archive or restore a goal for a site. order: 22 method: POST --- # Archive Goal Archives a goal so it no longer appears in stats. Historical conversion data is retained and the goal can be restored at any time. Requires member role or higher. ## Endpoint ``` POST /api/v1/organizations/:orgId/sites/:siteId/goals/:goalId/archive ``` # Restore Goal Restores a previously archived goal so it appears in stats again. ## Endpoint ``` POST /api/v1/organizations/:orgId/sites/:siteId/goals/:goalId/unarchive ``` --- URL: https://engagetrack.net/docs/api-reference/create-annotation.md --- title: Create Annotation description: Add an annotation to a site's analytics timeline. order: 43 method: POST --- # Create Annotation Creates a new annotation on the site's analytics timeline. Useful for marking deployments, campaigns, or other notable events. ## Endpoint ``` POST /api/v1/organizations/:orgId/sites/:siteId/annotations ``` ## Request Body | Field | Type | Required | Description | | ------------- | -------- | -------- | ----------------------------- | | `label` | `string` | Yes | Annotation label | | `occurred_at` | `string` | Yes | Annotation date (ISO 8601) | | `description` | `string` | No | Optional longer description | | `color` | `string` | No | Optional color for the marker | --- URL: https://engagetrack.net/docs/api-reference/create-funnel.md --- title: Create Funnel description: Create a new conversion funnel. order: 31 method: POST --- # Create Funnel Creates a new multi-step conversion funnel for a site. Requires member role or higher. ## Endpoint ``` POST /api/v1/organizations/:orgId/sites/:siteId/funnels ``` ## Request Body | Field | Type | Required | Description | | ------------- | -------- | -------- | ----------------------------- | | `name` | `string` | Yes | Funnel name | | `description` | `string` | No | Funnel description | | `steps` | `array` | Yes | Array of funnel steps (min 2) | Each step requires: | Field | Type | Required | Description | | ------------ | -------- | -------- | -------------------------------------- | | `name` | `string` | Yes | Step label | | `order` | `number` | Yes | Step position (1-indexed) | | `type` | `string` | No | `pageview` (default) or `custom_event` | | `pattern` | `string` | Yes | Page path or event name to match | | `match_type` | `string` | No | `exact`, `contains` (default), `regex` | ## Analyze Funnel Once created, analyze funnel performance: ``` GET /api/v1/organizations/:orgId/sites/:siteId/funnels/:funnelId/analyze ``` Returns per-step stats with: | Field | Type | Description | | ----------------- | -------- | -------------------------------------- | | `step_id` | `string` | Step ID | | `name` | `string` | Step name | | `order` | `number` | Step position | | `visitors` | `number` | Visitors who reached this step | | `dropoff_rate` | `number` | % lost from previous step | | `conversion_rate` | `number` | % retained from previous step | | `revenue` | `number` | Revenue attributed to visitors at step | | `top_sources` | `array` | Top 3 traffic sources at step | | `top_countries` | `array` | Top 3 countries at step | --- URL: https://engagetrack.net/docs/api-reference/create-invite.md --- title: Create Invite description: Invite a new team member to an organization. order: 51 method: POST --- # Create Invite Sends an invitation email to add a new member to the organization. Requires admin role. ## Endpoint ``` POST /api/v1/organizations/:orgId/team/invites ``` ## Request Body | Field | Type | Required | Description | | ------- | -------- | -------- | ------------------------------------------- | | `email` | `string` | Yes | Email address to invite | | `role` | `string` | Yes | Role to assign: `admin`, `member`, `viewer` | --- URL: https://engagetrack.net/docs/api-reference/create-site.md --- title: Create Site description: Add a new site to an organization. order: 11 method: POST --- # Create Site Creates a new site in the specified organization. Requires admin role. ## Endpoint ``` POST /api/v1/organizations/:orgId/sites ``` ## Request Body | Field | Type | Required | Description | | ---------- | -------- | -------- | -------------------------------- | | `domain` | `string` | Yes | Site domain (e.g. `example.com`) | | `name` | `string` | No | Display name | | `timezone` | `string` | No | IANA timezone (default: UTC) | The response includes a `public_id` — this is the site key used in the tracking script. This endpoint requires JWT authentication and is not accessible via API key. --- URL: https://engagetrack.net/docs/api-reference/ingest-event.md --- title: Ingest Event description: Send a pageview or custom event from the tracking script. order: 60 method: POST --- # Ingest Event The primary data ingestion endpoint used by the EngageTrack tracking script. Receives pageview and custom event payloads. This endpoint is called automatically by the tracking script. You typically don't need to call it directly unless building a custom integration. ## Endpoint ``` POST /api/v1/event ``` No Bearer token required — the site is identified by the `site_id` field (the site's public ID). ## Request Body | Field | Type | Required | Description | | -------------- | -------- | -------- | ------------------------------------------ | | `site_id` | `string` | Yes | Site public ID (`pk_live_*`) | | `event_type` | `string` | No | `pageview`, `click`, `form_submit`, `download`, `outbound`, `purchase`, `custom` | | `url` | `string` | Yes | Full page URL | | `event_name` | `string` | No | Custom event name (for custom events) | | `referrer` | `string` | No | Referrer URL | | `title` | `string` | No | Page title | | `visitor_uid` | `string` | No | Persistent visitor ID from localStorage | | `session_id` | `string` | No | Client-side session ID | | `screen_w` | `number` | No | Screen width | | `screen_h` | `number` | No | Screen height | | `time_on_page` | `number` | No | Seconds spent on previous page | | `scroll_depth` | `number` | No | Max scroll percentage (0-100) | | `revenue` | `number` | No | Revenue amount (for purchase events) | | `currency` | `string` | No | Currency code, e.g. `USD` | | `order_id` | `string` | No | Order ID (for purchase events) | | `properties` | `object` | No | Custom key-value properties | ## Response Returns `202 Accepted` with body `ok` on success. ## Identify Endpoint To link an anonymous visitor to a known user identity: ``` POST /api/v1/identify ``` | Field | Type | Required | Description | | ------------- | -------- | -------- | -------------------------------- | | `site_id` | `string` | Yes | Site public ID | | `visitor_uid` | `string` | Yes | Visitor UID from tracker | | `user_id` | `string` | Yes | Your application's user ID | | `name` | `string` | No | User display name | | `email` | `string` | No | User email | | `avatar` | `string` | No | Avatar URL | | `custom` | `object` | No | Custom attributes | --- URL: https://engagetrack.net/docs/api-reference/update-goal.md --- title: Update Goal description: Update an existing goal. order: 21 method: PUT --- # Update Goal Updates the configuration of an existing goal. Requires member role or higher. ## Endpoint ``` PUT /api/v1/organizations/:orgId/sites/:siteId/goals/:goalId ``` ## Request Body | Field | Type | Required | Description | | --------------------- | -------- | -------- | ---------------------------------- | | `name` | `string` | No | Goal display name | | `pattern` | `string` | No | Page path or event name to match | | `match_type` | `string` | No | `exact`, `contains`, or `regex` | | `value` | `number` | No | Monetary value per conversion | | `currency` | `string` | No | Currency code (e.g. `USD`) | | `property_conditions` | `array` | No | Property filters for custom events | The `type` field is immutable — goals are auto-created as `custom_event` or `pageview` and cannot change type after creation. --- URL: https://engagetrack.net/docs/api-reference/delete-annotation.md --- title: Delete Annotation description: Remove an annotation from a site. order: 44 method: DELETE --- # Delete Annotation Permanently deletes an annotation from the site's analytics timeline. ## Endpoint ``` DELETE /api/v1/organizations/:orgId/sites/:siteId/annotations/:annotationId ``` This action cannot be undone. The annotation will be permanently removed. --- URL: https://engagetrack.net/docs/api-reference/delete-funnel.md --- title: Delete Funnel description: Delete a funnel from a site. order: 32 method: DELETE --- # Delete Funnel Permanently deletes a funnel and its step definitions. Requires member role or higher. ## Endpoint ``` DELETE /api/v1/organizations/:orgId/sites/:siteId/funnels/:funnelId ``` --- URL: https://engagetrack.net/docs/api-reference/delete-site.md --- title: Delete Site description: Remove a site and all its data. order: 12 method: DELETE --- # Delete Site Permanently deletes a site and all associated analytics data. This action cannot be undone. Requires admin role. ## Endpoint ``` DELETE /api/v1/organizations/:orgId/sites/:siteId ``` ## Request Body | Field | Type | Required | Description | | ---------------- | -------- | -------- | ---------------------------------------------- | | `confirm_domain` | `string` | Yes | Must match the site's domain for confirmation | This permanently deletes all pageviews, events, goals, funnels, and visitor data for the site. Make sure to export any data you need before deleting. This endpoint requires JWT authentication and is not accessible via API key. --- URL: https://engagetrack.net/docs/troubleshooting/common-issues.md --- title: Troubleshooting description: Solutions to common EngageTrack issues and how to debug tracking problems. order: 1 --- # Troubleshooting This guide covers the most common issues and how to diagnose them. ## Enable Debug Mode The first step for any tracking issue is to enable debug mode. Add `data-debug="true"` to your script tag: ```html ``` Open your browser's developer console (F12 or Cmd+Option+I). You will see detailed logs prefixed with `[EngageTrack]` for every action the SDK takes. --- ## Script Not Loading **Symptoms:** No `[EngageTrack]` messages in the console. The script file returns a network error. ### Check Content Security Policy (CSP) If your site uses a Content Security Policy, make sure it allows the EngageTrack domains: ``` Content-Security-Policy: script-src 'self' https://cdn.engagetrack.net; connect-src 'self' https://api.engagetrack.net; ``` Check the console for CSP violation errors (they appear as red error messages mentioning "Content Security Policy"). ### Check for Ad Blockers Ad blockers may block `cdn.engagetrack.net` or `api.engagetrack.net`. To verify: 1. Disable your ad blocker temporarily 2. Reload the page 3. If tracking works, set up a [proxy](/docs/proxy/overview) to serve the script from your own domain ### Verify the Script Tag Make sure the script tag is correct: - The `src` URL is `https://cdn.engagetrack.net/sdk.js` - The `data-site-id` attribute is present and not empty - The `defer` attribute is included (the script needs the DOM to be ready) - The script is in the `` section --- ## No Data in Dashboard **Symptoms:** The script loads and debug logs appear, but no data shows in the dashboard. ### Wrong Site ID The `data-site-id` in your script tag must match the site ID in your EngageTrack dashboard. Copy it from **Site Settings -> General**. ### Domain Mismatch If you have an allowed hostnames list configured in **Site Settings -> Tracking**, the domain your site is served from must be in that list. Check that: - `localhost` is included if you are testing locally - The exact hostname matches (e.g., `www.example.com` and `example.com` are different) ### Events Blocked Server-Side Check the Network tab in your browser's developer tools: 1. Filter by `event` to find the POST request to the event endpoint 2. If the response is `403`, your IP may be excluded or the site ID is invalid 3. If the response is `429`, you have hit a rate limit New events typically appear in the dashboard within 5-10 seconds. If you are looking at the **Real-time** view, make sure you have selected the correct site from the dropdown. --- ## Revenue Not Appearing **Symptoms:** Purchases happen but no revenue data shows in the Revenue dashboard. ### Verify Webhook URL Each payment provider requires a webhook to send purchase events to EngageTrack: 1. Go to **Site Settings -> Revenue** 2. Check that your provider is connected and the webhook URL is configured 3. For Stripe, the connection is automatic via OAuth. For other providers, verify the webhook URL is set in the provider's dashboard. ### Check Metadata (Stripe) For Stripe integrations, the `engagetrack_visitor_id` must be included in the checkout session metadata for direct attribution: ```javascript const session = await stripe.checkout.sessions.create({ metadata: { engagetrack_visitor_id: visitorId, }, // ... }); ``` Without this metadata, EngageTrack falls back to email-based or session-based attribution, which may not match all purchases. ### Provider Webhook Logs Check your payment provider's webhook delivery logs for failed deliveries: - **Stripe:** Dashboard -> Developers -> Webhooks -> Select endpoint -> Recent deliveries - **Lemon Squeezy:** Settings -> Webhooks -> Click the webhook -> Delivery attempts - **Paddle:** Developer Tools -> Notifications -> Event log - **Polar:** Settings -> Webhooks -> Delivery history Revenue data may take up to 60 seconds to appear after a webhook is received, as the backend processes attribution asynchronously. --- ## Cross-Domain Tracking Not Working **Symptoms:** Visitors get a new visitor ID when navigating between domains. ### Check Allowed Hostnames Verify that `data-allowed-hostnames` includes the destination domain on the **source** site: ```html ``` ### Check URL Parameters When you click a link to the destination domain, the URL should include `_et_vid` and `_et_sid` parameters. If they are missing: 1. Enable debug mode on the source domain 2. Click the cross-domain link 3. Look for `[EngageTrack] Cross-domain link decorated:` in the console 4. If this log does not appear, the destination hostname is not in the allowed list ### Same Site ID Both domains must use the same `data-site-id` for the sessions to be stitched together. > See the full [Cross-Domain Tracking guide](/docs/advanced/cross-domain) for setup details. --- ## Real-Time Dashboard Not Updating **Symptoms:** The real-time view shows stale data or "0 current visitors" despite active traffic. ### WebSocket Connection The real-time dashboard uses WebSocket connections. Check for issues: 1. Open the Network tab and filter by "WS" (WebSocket) 2. You should see an active WebSocket connection to the API 3. If the connection fails, check that your network/firewall allows WebSocket connections ### Browser Tab Focus Some browsers throttle background tabs, which can delay WebSocket messages. Make sure the dashboard tab is in the foreground. ### Proxy Configuration If you are using a reverse proxy (Nginx, Cloudflare), ensure it supports WebSocket upgrades: ```nginx # Nginx WebSocket support location /ws { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } ``` --- ## Self-Visits Inflating Data **Symptoms:** Your own visits are being counted, inflating pageview and visitor numbers. Exclude yourself using one of these methods: ```javascript // Run this in the browser console on your tracked site window.engagetrack.ignore(); // Then reload the page ``` Or exclude your IP address in **Site Settings -> Tracking -> Excluded IPs**. > See [Exclude Visits](/docs/advanced/exclude-visits) for all exclusion options. --- ## Debugging Checklist If you are still stuck, work through this checklist: 1. **Script loads?** Check the Network tab for the SDK request. Status should be 200. 2. **SDK initializes?** With `data-debug="true"`, look for `[EngageTrack] Initialized with site:` in the console. 3. **Events sent?** In the Network tab, filter by the event endpoint URL. Check that POST requests are being made. 4. **Events accepted?** The event endpoint should return a `200` or `202` status. Any other status indicates a problem. 5. **Correct site?** Compare the `site_id` in the request payload with the site ID in your dashboard. 6. **Not excluded?** Check that `localStorage.engagetrack_ignore` is not set to `"true"`. 7. **Dashboard filters?** Make sure no filters are active in the dashboard that would hide your data. If none of the above resolves your issue, reach out to support with the following details: your site ID, the debug console output, and a screenshot of the Network tab showing the event request and response.