# Type-safe events Typos in event names silently split your data — `signup_completed` and `signup_complete` become two different events. Declare your events once and TypeScript autocompletes names and checks property shapes everywhere you track. ## NPM package Either pass an event map as a generic, or augment the global `DtcEventMap` interface once — the augmentation types every tracker in your project, including `window.__dtc`. **Explicit generic** ```typescript import { createTracker } from '@didtheyclick/sdk'; type MyEvents = { signup_completed: { plan: string }; purchase_promo: { code: string }; }; const tracker = createTracker({ websiteId: 'YOUR_API_KEY', endpoint: 'https://www.didthey.click/api/collect' }); tracker.track('signup_completed', { plan: 'pro' }); // ✅ autocompleted tracker.track('signup_compleded', {}); // ❌ compile error ``` **Global augmentation** ```typescript // dtc.d.ts — anywhere in your project's include path declare global { interface DtcEventMap { signup_completed: { plan: string }; purchase_promo: { code: string }; } } export {}; // Every tracker is now typed — no generic needed: // createTracker(), createServerTracker() (from // '@didtheyclick/sdk/server') and window.__dtc // all autocomplete your event names. ``` The same `DtcEventMap` augmentation also types `createServerTracker` from `@didtheyclick/sdk/server`, so client and server events share one definition. ## Declare your events The tracker lives on `window.__dtc`. Declare its types once in a `.d.ts` file anywhere in your project: **dtc.d.ts** ```typescript // dtc.d.ts — anywhere in your project's include path export {}; declare global { interface DtcEventMap { signup_completed: { plan: string }; purchase_promo: { code: string }; } interface Window { __dtc?: { track( name: K, properties?: DtcEventMap[K] ): void; identify(userId: string, traits?: Record): void; page(): void; }; } } ``` **Usage** ```typescript window.__dtc?.track('purchase_promo', { code: 'LAUNCH20' }); // ✅ window.__dtc?.track('purchase_prom0'); // ❌ compile error ``` > **Note: Compile-time only** > > These types exist purely in your editor and build. The tracker accepts any event name at runtime — nothing breaks for untyped callers, and events won't be rejected if the types drift. > **Tip: Keep values as strings** > > Event properties are string key/value pairs on the wire. Stick to `string` values in your event map so the types match what's actually sent.