tracklane 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,166 +0,0 @@
1
- import { c as UserData, i as EventData, n as ConsentState, o as ProviderDefault, r as EventBinding, s as TrackingError, t as ActionSource } from "./vocabulary-fzM9ZuE1.js";
2
- //#region src/providers/ga4.server.d.ts
3
- /** Credentials for the GA4 Measurement Protocol. */
4
- interface Ga4ServerCredentials {
5
- /** The `G-` id of the data stream. */
6
- measurementId: string;
7
- /** Created under Admin → Data Streams → Measurement Protocol. */
8
- apiSecret: string;
9
- }
10
- /** Optional configuration for the GA4 server provider. */
11
- interface Ga4ServerConfig {
12
- events?: Record<string, EventBinding<string>>;
13
- }
14
- /**
15
- * Google Analytics 4 on the server, through the Measurement Protocol.
16
- *
17
- * @param credentials - The measurement id and API secret.
18
- * @param config - Rarely needed event name overrides.
19
- * @returns A provider for `createTracking` from `tracklane/server`.
20
- *
21
- * @example
22
- * ```ts
23
- * import { createTracking, ga4 } from 'tracklane/server';
24
- *
25
- * const { track } = createTracking({
26
- * providers: [ga4({ measurementId: 'G-XXXXXXX', apiSecret: process.env.GA4_SECRET! })],
27
- * });
28
- *
29
- * await track('purchase', order, { cookies: request.headers.get('cookie') });
30
- * ```
31
- */
32
- declare function ga4(credentials: Ga4ServerCredentials, config?: Ga4ServerConfig): ServerProvider;
33
- //#endregion
34
- //#region src/server.d.ts
35
- /**
36
- * Everything a conversion API needs beyond the event itself: who the person
37
- * is, when it happened, and where it was observed.
38
- *
39
- * None of this is "what happened", which is why it does not travel in the
40
- * event data: putting it there would leak identity into the pass-through
41
- * event params of the vendors that forward the payload as-is.
42
- */
43
- interface EventContext {
44
- /** The person's identity, the server-side counterpart to `identify()` on the browser. */
45
- user?: UserData;
46
- /**
47
- * The request's raw `Cookie` header, or an already-parsed map.
48
- *
49
- * These are cookies the vendors' own browser tags set. This library never
50
- * writes one. On the server each adapter reads the cookies belonging to
51
- * its own vendor: Meta forwards its value as-is, Google's holds several
52
- * things at once and has to be opened. That knowledge lives in the
53
- * adapters; the core only splits `name=value; name=value` into pairs.
54
- *
55
- * **It splits, it does not interpret.** Values are handed over exactly as
56
- * they appear, with no percent-decoding. The cookies these vendors set do
57
- * not need it; a host reading some other cookie should decode it itself.
58
- */
59
- cookies?: string | Record<string, string> | null;
60
- /** Ties this send to a browser hit. Never invented by the library. */
61
- dedupId?: string;
62
- /**
63
- * When the conversion actually happened. Defaults to now.
64
- *
65
- * A webhook arrives after the fact and LinkedIn rejects conversions older
66
- * than 90 days, so reporting "now" for everything would quietly distort
67
- * attribution.
68
- */
69
- timestamp?: number | Date;
70
- /** Overrides the factory default. Meta requires it on every event. */
71
- source?: ActionSource;
72
- /** The page the conversion happened on. Meta's Conversions API reads it as `event_source_url`. */
73
- url?: string;
74
- /** The visitor's IP. Meta's Conversions API reads it as one of the identifiers in `user_data`. */
75
- ip?: string;
76
- /** The visitor's user agent. Meta's Conversions API reads it alongside `ip`. */
77
- userAgent?: string;
78
- /** What is known *about* the person: GA4 user properties, PostHog `$set`. */
79
- traits?: Record<string, unknown>;
80
- /**
81
- * Travels inside the event, for the vendors that document such a field.
82
- * Today that is GA4's Measurement Protocol, and it reads two of the
83
- * signals; the others have no slot and ignore it.
84
- */
85
- consent?: ConsentState;
86
- }
87
- /** The context an adapter receives, with the ambiguity resolved. */
88
- interface ResolvedContext extends Omit<EventContext, "cookies" | "timestamp"> {
89
- /** The request's cookies, already split into a `name → value` map. */
90
- cookies: Record<string, string>;
91
- /** Epoch milliseconds. Adapters convert to their vendor's spelling. */
92
- timestamp: number;
93
- }
94
- /**
95
- * A destination for server events.
96
- *
97
- * `track` may throw, on a non-2xx or where a vendor documents a
98
- * precondition the event cannot meet. The dispatcher isolates and reports
99
- * it, so adapters stay honest and loud.
100
- *
101
- * `report` is for a caveat about a request that already succeeded. It does
102
- * not throw: by then the send happened, and throwing would tell a host's
103
- * retry logic to resend a delivered conversion.
104
- */
105
- interface ServerProvider<Target = string> {
106
- /** The vendor's fixed name. Registering one twice is an error. */
107
- name: string;
108
- /** What happens to a canonical event this vendor has no binding for. */
109
- default: ProviderDefault;
110
- /** How this vendor spells each canonical event. */
111
- events?: Record<string, EventBinding<Target>>;
112
- /** Sends one event to this vendor's conversion API. May throw, or call `report` for a caveat. */
113
- track(name: Target, data: EventData, context: ResolvedContext, report: (message: string) => void): Promise<void>;
114
- }
115
- /** Options accepted by {@link createTracking}. */
116
- interface ServerTrackingOptions {
117
- /** The vendors to send every event to. Registering the same `name` twice throws. */
118
- providers: readonly ServerProvider[];
119
- /**
120
- * The one diagnostic channel. Without it the library is silent, exactly as
121
- * a hand-written vendor call is.
122
- */
123
- onError?: (error: TrackingError) => void;
124
- }
125
- /** What {@link createTracking} returns. */
126
- interface ServerTracking {
127
- /**
128
- * Sends one event to every configured conversion API.
129
- *
130
- * Resolves once every provider has settled and never rejects: one vendor
131
- * being down is not the caller's failure to handle. Awaiting is about the
132
- * request surviving a serverless runtime, not about delivery being
133
- * guaranteed.
134
- */
135
- track(name: string, data?: EventData, context?: EventContext): Promise<void>;
136
- }
137
- /**
138
- * Creates the server tracking surface.
139
- *
140
- * There is no `identify` here and nothing is held between calls: a server
141
- * instance is shared by every request, so a retained identity would attach
142
- * one visitor to another visitor's conversion. Identity travels with the
143
- * call, which is also what every conversion API expects.
144
- *
145
- * There is no `consent` call either. Consent commands are properties of a
146
- * vendor's on-page tag, and a server request has no tag. The one vendor that
147
- * accepts consent server-side reads it from the context.
148
- *
149
- * @param options - The providers to send to, and an optional error channel.
150
- * @returns The `track` call.
151
- *
152
- * @example
153
- * ```ts
154
- * import { createTracking, ga4 } from 'tracklane/server';
155
- *
156
- * const { track } = createTracking({
157
- * providers: [ga4({ measurementId: 'G-XXXXXXX', apiSecret })],
158
- * });
159
- *
160
- * await track('purchase', order, { cookies: request.headers.get('cookie') });
161
- * ```
162
- */
163
- declare function createTracking(options: ServerTrackingOptions): ServerTracking;
164
- //#endregion
165
- export { ServerTrackingOptions as a, Ga4ServerCredentials as c, ServerTracking as i, ga4 as l, ResolvedContext as n, createTracking as o, ServerProvider as r, Ga4ServerConfig as s, EventContext as t };
166
- //# sourceMappingURL=server-DRda44Tb.d.ts.map
@@ -1,129 +0,0 @@
1
- //#region src/vocabulary.d.ts
2
- /**
3
- * The vocabulary shared by the browser and server libraries.
4
- *
5
- * These two libraries never talk to each other. They share no runtime, no
6
- * state, no instance in common. What they share is this: the names of
7
- * events and the shape of the data that travels with them, so that
8
- * `purchase` means the same thing on both sides. This is the only overlap
9
- * that exists on purpose.
10
- */
11
- /** One item inside an ecommerce event, spelled the way GA4 spells it. */
12
- interface EventItem {
13
- /** The SKU or catalogue id for this line. */
14
- item_id?: string;
15
- /** The product name for this line, shown in reports. */
16
- item_name?: string;
17
- /** The unit price for this line, before `quantity`. */
18
- price?: number;
19
- /** How many units of this line. */
20
- quantity?: number;
21
- [key: string]: unknown;
22
- }
23
- /**
24
- * The business payload of an event.
25
- *
26
- * The named fields are the ones adapters read to build vendor-specific value
27
- * and content slots. The index signature is deliberate: a business measures
28
- * things this vocabulary does not name, and closing the bag would make the
29
- * library the arbiter of what may be measured.
30
- */
31
- interface EventData {
32
- /** The order id. GA4 needs it, together with `items`, to record a purchase. */
33
- transaction_id?: string;
34
- /** The monetary amount, paired with `currency`. */
35
- value?: number;
36
- /** An ISO 4217 code. GA4 requires it whenever `value` is set. */
37
- currency?: string;
38
- /** The cart or order lines, required by GA4 alongside `transaction_id` for a purchase. */
39
- items?: EventItem[];
40
- [key: string]: unknown;
41
- }
42
- /**
43
- * Who the person is.
44
- *
45
- * One identifier for the person, which every vendor receives under its own
46
- * name. Values are always raw: hashing and normalisation are field formats
47
- * each vendor defines, applied inside the adapter that owns the field.
48
- *
49
- * Everything else that identifies someone arrives through cookies on the
50
- * server, read by whichever adapter knows the format.
51
- */
52
- interface UserData {
53
- /** One id for the person, translated per vendor. */
54
- userId?: string;
55
- /** Raw and unhashed. Adapters that need it hashed (Meta, LinkedIn) do that themselves. */
56
- email?: string;
57
- /** Raw, in whatever format the host has it. An adapter normalises it if its vendor needs to. */
58
- phone?: string;
59
- /** Raw, read only by vendors whose identity match uses names, such as Meta. */
60
- firstName?: string;
61
- /** Raw, read only by vendors whose identity match uses names, such as Meta. */
62
- lastName?: string;
63
- /** From the URL rather than a cookie, which is why it is named here. */
64
- twclid?: string;
65
- }
66
- /**
67
- * Consent signals, in Google's own spelling.
68
- *
69
- * Google's is the most granular surface any of the five vendors exposes, so
70
- * every other vendor receives a *collapse* of it. Carrying the finest
71
- * resolution and reducing per vendor means a projection never claims more
72
- * than the host declared. Expanding a coarse answer into fine signals would
73
- * invent information, and this library never does that.
74
- *
75
- * An absent signal produces no key. Treating silence as a denial would put
76
- * words in the visitor's mouth, just as treating it as a grant would.
77
- */
78
- interface ConsentState {
79
- /** Governs Google's ad cookies. Browser only, since GA4's server-side API has no slot for it. */
80
- ad_storage?: "granted" | "denied";
81
- /** Governs Google's analytics cookies. Browser only, since GA4's server-side API has no slot. */
82
- analytics_storage?: "granted" | "denied";
83
- /** Whether user data may be sent for ads. GA4's server-side API reads this one, uppercased. */
84
- ad_user_data?: "granted" | "denied";
85
- /** Whether ads may be personalised. GA4's server-side API reads this one too, uppercased. */
86
- ad_personalization?: "granted" | "denied";
87
- }
88
- /**
89
- * Where a conversion happened.
90
- *
91
- * Meta's vocabulary, adopted verbatim, because it is the only vendor of the
92
- * five that documents the concept and requires the field on every server
93
- * event. Inventing a taxonomy and translating it would be both incomplete
94
- * for Meta and meaningless to everyone else.
95
- */
96
- type ActionSource = "website" | "app" | "email" | "phone_call" | "chat" | "physical_store" | "system_generated" | "business_messaging" | "other";
97
- /**
98
- * How a canonical event name is spelled for one vendor, or `null` to say
99
- * "never send this event here".
100
- */
101
- type EventBinding<Target> = Target | null;
102
- /** What a provider does with a canonical event it has no binding for. */
103
- type ProviderDefault = "passthrough" | "ignore";
104
- /**
105
- * Reported out of band, never thrown at the call site.
106
- *
107
- * Fanning out to N vendors means no single call site can catch anything, so
108
- * this is the replica of the `try/catch` a host would have written around a
109
- * hand-made call. `severity` separates "this did not arrive" from "this
110
- * arrived, and here is something you should know".
111
- *
112
- * It never carries event contents: the payload holds raw personal data by
113
- * design, and no library-owned surface re-emits it into a host's logs.
114
- */
115
- interface TrackingError {
116
- /** Which vendor produced this. It matches the `name` on the provider that registered it. */
117
- provider: string;
118
- /** The canonical event name being sent when this happened. */
119
- event: string;
120
- /** `'error'` when the event did not arrive; `'warning'` when it arrived but is worth a look. */
121
- severity: "error" | "warning";
122
- /** What happened, in one line, excluding the payload: event data never appears here. */
123
- message: string;
124
- /** The original thrown value, where one exists, for a host that wants more than `message`. */
125
- cause?: unknown;
126
- }
127
- //#endregion
128
- export { EventItem as a, UserData as c, EventData as i, ConsentState as n, ProviderDefault as o, EventBinding as r, TrackingError as s, ActionSource as t };
129
- //# sourceMappingURL=vocabulary-fzM9ZuE1.d.ts.map