/** * VTilt Types * * Type definitions for the VTilt tracking SDK. * Following PostHog's patterns where applicable. */ interface FeatureFlagsConfig { [flagKey: string]: boolean | string; } type GoogleConsentValue = "follow_advertising" | "follow_analytics" | "granted" | "denied"; interface GoogleConsentOverride { ad_storage?: GoogleConsentValue; ad_user_data?: GoogleConsentValue; ad_personalization?: GoogleConsentValue; analytics_storage?: GoogleConsentValue; } interface GoogleAdsConversionMapping { event_name: string; send_to: string; value_param_path?: string; currency_param_path?: string; default_currency?: string; send_transaction_id?: boolean; transaction_id_param_path?: string; } /** * How gtag.js is loaded — mirrors the server-side `proxy_mode` destination * setting: * * - `proxied` (default) — route through `api_host/gt/*`. `api_host` is the * SDK-level proxy setting; self-hosted customers point it at their own * domain (which must implement the `/gt/*` spec). * - `direct` — no proxy; gtag.js loads straight from * `https://www.googletagmanager.com/gtag/js`. */ type GoogleTagProxyMode = "proxied" | "direct"; /** * Configuration for the Google Tag Gateway SDK feature. Ships under the * `googleTag` key of /decide when at least one `ga4_gtag` or `google_ads_gtag` destination is * enabled for the project. */ interface GoogleTagClientConfig { destinationId: string; /** * Proxy mode. When absent the SDK falls back to `proxied` so older * `/decide` responses and the zero-config default remain compatible. */ proxyMode?: GoogleTagProxyMode; tagIds: string[]; conversions: GoogleAdsConversionMapping[]; enhancedConversions: boolean; conversionLinker: boolean; linkerDomains: string[]; capturePageview: boolean; debugMode: boolean; consentOverride?: GoogleConsentOverride; /** * Master switch for forwarding every `vt.capture()` event to GA4 via * `gtag('event', name, params)`. Defaults to `true` when absent. When * `false`, only events that match an explicit row in `eventMappings` — or * an Ads `conversions` mapping — fire; everything else is left to the * Google tag's own behavior (page_view, enhanced measurement, etc.). */ autoForward?: boolean; /** * Whether to fire the direct Ads conversion beacon * (`gtag('event', 'conversion', {send_to: 'AW-.../...'})`) for rows in * `conversions`. Defaults to `true` when absent. Turn off when GA4 is * linked to Google Ads in the Ads account — in that mode the GA4 event * (marked as a conversion in GA4) propagates to Ads automatically and * the direct beacon would duplicate it. Has no effect when `conversions` * is empty. */ sendAdsConversions?: boolean; /** * Admin-configured event renames and param remappings. Mirrors the * generic `event_mappings` configured on the destination. Applied after * the filter check and before firing `gtag('event', ...)`. */ eventMappings?: GoogleTagEventMapping[]; /** * Admin-configured include/exclude lists. Mirrors the generic * `event_filter` on the destination. Evaluated before any mapping. */ eventFilter?: { include?: string[]; exclude?: string[]; }; } /** * Rename an event and optionally remap payload paths to gtag param paths. * Structurally identical to the server-side `EventMapping` type but lives * in the browser package to avoid cross-package imports. Source paths use * dotted notation into the captured payload (e.g. `order.total`); dest * paths use dotted notation into the outgoing gtag `params` object. */ interface GoogleTagEventMapping { source: string; destination: string; param_mappings?: GoogleTagParamMapping[]; } interface GoogleTagParamMapping { source: string; destination: string; } interface RemoteConfig { sessionRecording?: { enabled?: boolean; sampleRate?: number; minimumDurationMs?: number; /** Full DOM snapshot interval in ms (default 300000 = 5 min). Higher = less data. */ fullSnapshotIntervalMs?: number; maskAllInputs?: boolean; maskAllText?: boolean; captureConsole?: boolean; captureCanvas?: { recordCanvas?: boolean; canvasFps?: number; canvasQuality?: number; }; }; chat?: { enabled?: boolean; widgetPosition?: "bottom-right" | "bottom-left"; widgetColor?: string; bubbleDraggable?: boolean; bubbleVisible?: boolean; }; chatTracking?: { trackUserMessages?: boolean; trackAgentMessages?: boolean; }; analytics?: { capturePageview?: boolean; capturePageleave?: boolean; capturePerformance?: boolean; autocapture?: boolean; scrollDepthMilestones?: boolean; scrollDepthPageleave?: boolean; }; privacy?: { respectDnt?: boolean; requireConsent?: boolean; ipAnonymization?: boolean; }; /** * Diagnostics — runtime-tunable console verbosity. Applied by the SDK only * when the integrator did NOT pass `log_level` / `debug` to `vt.init()`. * Set from the dashboard's Default Configuration → Diagnostics tab. */ diagnostics?: { defaultLogLevel?: "none" | "error" | "warn" | "info" | "debug"; }; featureFlags?: FeatureFlagsConfig; /** Whether to send elements as chain string (PostHog compatibility) */ elementsChainAsString?: boolean; /** Server-side autocapture opt-out */ autocapture_opt_out?: boolean; /** * Google Tag Gateway config (absent when no client Google gtag destination is * enabled for the project). Drives the gtag.js proxy loader, Consent Mode * v2 bridge, and event → conversion mappings. */ googleTag?: GoogleTagClientConfig; /** * Outbound surfaces (banner). `enabled` is derived server-side from whether * the project has an active message, so operators publish from the dashboard * instead of editing `vt.init`. Off means there is nothing to show, so the * lazy `outbound.js` bundle is never fetched. */ outbound?: { enabled?: boolean; }; } /** * Server-side utilities for vTilt SDK * Use these in Next.js Server Components or API routes to fetch remote config * and pass it to the client via bootstrap for instant initialization. */ interface FetchRemoteConfigOptions { /** vTilt API host (e.g., 'https://your-vtilt-instance.com') */ apiHost: string; /** Project API token (e.g., 'vt_abc123...') */ token: string; /** Request timeout in milliseconds (default: 3000) */ timeout?: number; } /** * Fetch remote config from the /decide endpoint (server-side) * * Use this in Next.js Server Components or getServerSideProps to fetch * the remote config and pass it to the client via bootstrap. * * @example * ```tsx * // app/layout.tsx (Next.js App Router) * import { fetchRemoteConfig } from '@v-tilt/browser/dist/server'; * * export default async function RootLayout({ children }) { * const remoteConfig = await fetchRemoteConfig({ * apiHost: process.env.VTILT_API_HOST!, * token: process.env.NEXT_PUBLIC_VTILT_TOKEN!, * }); * * return ( * *
*