The boilerplate includes consent-aware analytics integrations for tracking user behavior, conversions, and providing live customer support.
Google Tag Manager
Centralized tag management with consent mode.
Google Ads
Conversion tracking via gtag.js with dynamic values.
Meta Pixel
Facebook/Instagram conversion tracking.
Crisp Chat
Live chat with user identification.
Consent-Aware
GDPR-compliant cookie consent integration.
Google Tag Manager
Configure with NEXT_PUBLIC_GTM_ID for your GTM container (GTM-XXX). For GA4 and Google Ads, use the dedicated env vars (NEXT_PUBLIC_GA_MEASUREMENT_ID and NEXT_PUBLIC_GOOGLE_ADS_ID) which are handled by the GoogleAdsTag component.
| Env Variable | ID Format | Script Loaded | Component |
|---|---|---|---|
NEXT_PUBLIC_GTM_ID |
GTM-XXXXXXX |
gtm.js |
GoogleTagManager |
NEXT_PUBLIC_GA_MEASUREMENT_ID |
G-XXXXXXX |
gtag/js (primary) |
GoogleAdsTag |
NEXT_PUBLIC_GOOGLE_ADS_ID |
AW-XXXXXXX |
gtag/js (secondary config) |
GoogleAdsTag |
GTM (gtm.js) and gtag.js are loaded by separate components and coexist via the shared window.dataLayer. To avoid double-counting conversions, do not configure Google Ads conversion tags in your GTM container — use gtag.js for conversions (via NEXT_PUBLIC_GOOGLE_ADS_CONVERSION_PURCHASE / NEXT_PUBLIC_GOOGLE_ADS_CONVERSION_SIGNUP). All IDs are validated against strict regex patterns to prevent XSS via env injection.
| Feature | Description |
|---|---|
| Consent Mode | Integrates with the cookie consent banner. Analytics fires only after analytics consent, marketing/ad tags only after marketing consent, and Global Privacy Control keeps marketing consent disabled. |
| Page Views | Automatic page view tracking on route changes |
| User Events | Login, signup, and subscription events |
| E-commerce | Purchase and checkout events for Stripe |
| Custom Events | AI usage, chat sessions, and custom interactions |
Google Ads Conversion Tracking
Track Google Ads conversions via gtag.js with per-action conversion tags. The gtag.js script is loaded with async + Next.js strategy="afterInteractive", deferring the request until after hydration to keep it off the critical path while remaining detectable by Google Tag Assistant.
| Feature | Description |
|---|---|
| Google-Compliant Loading | gtag.js loaded with async + Next.js afterInteractive strategy — injected after hydration, still detected by Google Tag Assistant |
| Consent Mode v2 | Defaults to denied, instantly restores prior consent from localStorage (no hydration wait for returning users) |
| Per-Action Conversion Tags | NEXT_PUBLIC_GOOGLE_ADS_CONVERSION_PURCHASE (format: AW-XXX/LABEL) and NEXT_PUBLIC_GOOGLE_ADS_CONVERSION_SIGNUP — each event fires its own send_to |
| Auto-Fired: Purchase | Fires on checkout success page via trackConversion() with real Stripe session data (amount, currency, transaction ID) |
| Auto-Fired: Signup | Fires on onboarding completion via trackSignUp() — also triggers GTM sign_up + Meta Pixel CompleteRegistration |
| Pre-built Events | googleAdsEvents.purchase(), .lead(), .signUp(), .creditPurchase(), .custom() |
| Click Tracking | gtagReportConversion(url, params) — onClick handler that tracks conversion then redirects (with open-redirect protection) |
| Deduplication | Uses transaction_id to prevent duplicate conversions on page refresh |
| Unified Methods | trackConversion() and trackSignUp() via useAnalytics() hook fire Google Ads + GTM + Meta Pixel in one call |
| Security | Env var format validation (prevents XSS), URL protocol validation, Stripe session_id format check |
Usage Examples
// Via the unified analytics hook (recommended — respects consent)
const { trackConversion, trackSignUp } = useAnalytics()
// Purchase conversion (auto-fired on checkout success page)
trackConversion({
transactionId: 'cs_live_xxx',
value: 29.99,
currency: 'EUR',
})
// Signup conversion (auto-fired on onboarding completion)
trackSignUp()
// Direct Google Ads conversion with specific send_to
import { googleAdsEvents } from '@/components/analytics'
googleAdsEvents.purchase('txn_123', 29.99, 'EUR') // uses CONVERSION_PURCHASE
googleAdsEvents.signUp() // uses CONVERSION_SIGNUP
googleAdsEvents.lead(5.0) // uses CONVERSION_SIGNUP
// On button/link click with redirect
import { gtagReportConversion } from '@/components/analytics'
<button onClick={() => gtagReportConversion('/thank-you', { value: 29.99 })}>
Buy Now
</button>
GTM (gtm.js) and gtag.js coexist via the shared window.dataLayer. To prevent double-counting, do not configure Google Ads conversion tags in your GTM container — conversions are tracked via gtag.js using the per-action env vars (NEXT_PUBLIC_GOOGLE_ADS_CONVERSION_PURCHASE, NEXT_PUBLIC_GOOGLE_ADS_CONVERSION_SIGNUP).
Meta Pixel (Facebook)
Track conversions for Facebook and Instagram ads. Configure with NEXT_PUBLIC_META_PIXEL_ID.
- Loads only when marketing consent is granted
- Tracks PageView on route changes
- E-commerce events (Purchase, InitiateCheckout)
- Lead events (CompleteRegistration, Subscribe)
X (Twitter) Pixel
Track conversions for X (Twitter) Ads campaigns via the universal website tag (uwt.js). Configure with NEXT_PUBLIC_X_PIXEL_ID (base pixel ID from X Ads Manager, e.g. o1abc) plus the per-action event IDs NEXT_PUBLIC_X_PIXEL_EVENT_PURCHASE and NEXT_PUBLIC_X_PIXEL_EVENT_SIGNUP (format: tw-XXXXX-XXXXX). Loaded by the XPixel component (components/analytics/x-pixel.tsx) and orchestrated by AnalyticsProvider.
| Feature | Description |
|---|---|
| Marketing-Consent Gated | The pixel script mounts only after marketing consent is granted — identical handling to Meta Pixel (X Ads is a marketing cookie). When consent is missing the pixel is not loaded and conversion calls are silent no-ops. |
| Automatic Page View | The base twq('config', ID) call auto-tracks page views — no manual PageView event is fired (avoids double-counting). |
| Auto-Fired: Purchase | Fires on trackConversion() via xEvents.purchase({ value, currency, transactionId }) — uses NEXT_PUBLIC_X_PIXEL_EVENT_PURCHASE. Same call also fires Google Ads + GTM + Meta Pixel purchase events. |
| Auto-Fired: Signup | Fires on trackSignUp() via xEvents.signUp() — uses NEXT_PUBLIC_X_PIXEL_EVENT_SIGNUP. Triggered on onboarding completion. |
| Pre-built Events | xEvents.purchase(), .signUp(), .lead() (reuses signup ID), .custom(eventId, params) for additional conversion actions. Each no-ops cleanly when its env var is unset, so calling unconditionally is safe. |
| Security (Env Var Validation) | Pixel ID is validated against /^[A-Za-z0-9]{3,12}$/ and event IDs against /^tw-[A-Za-z0-9]+-[A-Za-z0-9]+$/ before injection into the inline script — prevents XSS via malformed env values. Invalid IDs are silently dropped (component renders null). |
| CSP-Compliant | Script receives the per-request nonce via the nonce prop. static.ads-twitter.com is in SCRIPT_CDN_ALLOWLIST and analytics.twitter.com / t.co are in CONNECT_CDN_ALLOWLIST in lib/security/csp.ts. |
Crisp Chat
Live chat widget for customer support. Configure with NEXT_PUBLIC_CRISP_WEBSITE_ID.
| Feature | Description |
|---|---|
| User Identification | Automatically identifies logged-in users with email, name, avatar |
| Company Data | Associates users with their workspace/company |
| Custom Data | Sends subscription plan, credits balance, account type |
| Locale Support | Chat interface matches user's locale |
| Programmatic Control | Open, close, hide, show, and send messages via API |