@shware/analytics 11.0.1 → 11.1.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.
package/README.md CHANGED
@@ -81,8 +81,10 @@ the events are the visitor's record. The server:
81
81
  the visitor id), `platform` and `environment` from the event, its tags (with the request's
82
82
  geolocation and user agent) as both `tags` and `initial_tags`, and the bot verdict from them.
83
83
  - **refreshes `visitor.tags` from each `session_start`**: `tags` is the last-touch counterpart to
84
- `initial_tags` (browser, release, landing), so once per session is enough, and the events route
85
- already writes the session row there.
84
+ `initial_tags` (browser, release, landing), and a session's opening is where a visit came in, so
85
+ once per session is both enough and the right moment. `setVisitor` sends no tags (11.1): at
86
+ sign-in the page is the login page, and its tags would overwrite the landing's. Clients before
87
+ 11.1 still send tags on their PATCH; merge them when present.
86
88
  - **does not create it on `PATCH /visitors/:id`** (`setVisitor`): that is a sign-in handing the
87
89
  user to the ad platforms' pixels and gtag, and by then the visitor's events have created it. On
88
90
  the rare page where a signed-in user's sign-in lands before the first batch of a new visitor id
@@ -148,13 +148,6 @@ const propertiesSchema = (0, zod_mini.optional)((0, zod_mini.pipe)((0, zod_mini.
148
148
  (0, zod_mini.null)(),
149
149
  items
150
150
  ])), (0, zod_mini.transform)(takeProperties)));
151
- /** Visitor properties differ from event properties only in taking no nested item lists. */
152
- const visitorPropertiesSchema = (0, zod_mini.optional)((0, zod_mini.pipe)((0, zod_mini.record)((0, zod_mini.string)(), (0, zod_mini.union)([
153
- propertyText,
154
- (0, zod_mini.number)(),
155
- (0, zod_mini.boolean)(),
156
- (0, zod_mini.null)()
157
- ])), (0, zod_mini.transform)(takeProperties)));
158
151
  /**
159
152
  * How far an event's time may be from the server's before the client clock it was stamped with is
160
153
  * taken as wrong. A batch legitimately arrives late — a tab frozen in the background, a
@@ -204,8 +197,7 @@ const createVisitorSchema = (0, zod_mini.object)({
204
197
  device_id: (0, zod_mini.string)().check((0, zod_mini.trim)(), (0, zod_mini.minLength)(1), (0, zod_mini.maxLength)(36)),
205
198
  platform: (0, zod_mini.enum)(ALL_PLATFORMS),
206
199
  environment: (0, zod_mini.enum)(ALL_ENVIRONMENTS),
207
- tags: tagsSchema,
208
- properties: visitorPropertiesSchema
200
+ tags: tagsSchema
209
201
  });
210
202
  const emailValue = (0, zod_mini.pipe)((0, zod_mini.string)().check((0, zod_mini.trim)(), (0, zod_mini.toLowerCase)(), (0, zod_mini.maxLength)(320)), (0, zod_mini.email)());
211
203
  /** E.164: a plus sign (+) prefix, country code, then digits only, no dashes/parens/spaces. */
@@ -239,8 +231,12 @@ const userProvidedDataSchema = (0, zod_mini.object)({
239
231
  const updateVisitorSchema = (0, zod_mini.object)({
240
232
  user_id: (0, zod_mini.optional)((0, zod_mini.uuid)()),
241
233
  user_data: (0, zod_mini.optional)(userProvidedDataSchema),
242
- tags: tagsSchema,
243
- properties: visitorPropertiesSchema
234
+ /**
235
+ * Sent by clients before 11.1, which PATCHed their tags on every page load. From 11.1 the
236
+ * server refreshes `visitor.tags` from each `session_start` — the moment the visit arrives —
237
+ * and `setVisitor` sends none: at sign-in the page is no longer where the visit came in.
238
+ */
239
+ tags: (0, zod_mini.optional)(tagsSchema)
244
240
  });
245
241
  const createFeedbackSchema = (0, zod_mini.object)({
246
242
  name: (0, zod_mini.string)().check((0, zod_mini.minLength)(1), (0, zod_mini.maxLength)(256)),
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["pipe","string","transform","array","record","union","number","boolean","_null","object","optional","trim","minLength","maxLength","regex","uuid","_enum","iso","toLowerCase","email","e164","toUpperCase","url"],"sources":["../../src/schema/index.ts"],"sourcesContent":["import {\n enum as _enum,\n null as _null,\n array,\n boolean,\n e164,\n email,\n iso,\n maxLength,\n minLength,\n number,\n object,\n optional,\n pipe,\n record,\n regex,\n string,\n toLowerCase,\n toUpperCase,\n transform,\n trim,\n union,\n url,\n uuid,\n type z,\n} from 'zod/mini';\nimport type { Environment, Platform } from '../track/types';\n\nconst MAX_KEY_LENGTH = 128;\nconst MAX_VALUE_LENGTH = 512;\nconst MAX_PROPERTIES = 64;\n\n/**\n * Truncated rather than rejected. These schemas validate a whole batch at once, so refusing one\n * oversized value costs every event that traveled with it — and the values that overrun are the\n * ones derived from the page (a link's text, a URL carrying a long query), which no client can\n * bound in advance. A shortened value is worth more than a lost batch.\n */\nconst propertyText = pipe(\n string(),\n transform((value) => value.slice(0, MAX_VALUE_LENGTH))\n);\n\n/**\n * Keys are written by hand in instrumentation code, so an unusable one is a mistake in the host\n * rather than something the visitor typed. It is still dropped rather than rejected, for the same\n * reason: the mistake should cost that property, not the batch it happens to be in. Truncating a\n * key is not an option — two long keys would silently become one field.\n *\n * The key schema below is deliberately permissive so that this transform is reached at all; the\n * trimming it used to do happens here instead. `MAX_PROPERTIES` keeps the first N in insertion\n * order.\n */\nfunction takeProperties<T>(data: Record<string, T>): Record<string, T> {\n const result: Record<string, T> = {};\n let count = 0;\n for (const [rawKey, value] of Object.entries(data)) {\n if (count >= MAX_PROPERTIES) break;\n const key = rawKey.trim();\n if (!key || key.length > MAX_KEY_LENGTH) continue;\n result[key] = value;\n count++;\n }\n return result;\n}\n\n/**\n * Capped at GA4's own item-list limit, and truncated rather than rejected like every other\n * property limit here: an unbounded array is the one field a caller could still blow a batch\n * up with after the value and key limits.\n */\nconst MAX_ITEMS = 200;\n\nconst items = pipe(\n array(\n pipe(\n record(string(), union([propertyText, number(), boolean(), _null()])),\n transform(takeProperties)\n )\n ),\n transform((list) => list.slice(0, MAX_ITEMS))\n);\n\nexport const ALL_PLATFORMS = [\n 'ios',\n 'android',\n 'web',\n 'macos',\n 'windows',\n 'linux',\n 'unknown',\n] as const satisfies Platform[];\n\nexport const ALL_ENVIRONMENTS = ['development', 'production'] as const satisfies Environment[];\n\nexport const tagsSchema = object({\n os: optional(string()),\n os_name: optional(string()),\n os_version: optional(string()),\n browser: optional(string()),\n browser_name: optional(string()),\n browser_version: optional(string()),\n device: optional(string()),\n device_id: optional(string().check(trim(), minLength(1), maxLength(36))),\n device_type: optional(string()),\n device_vendor: optional(string()),\n device_pixel_ratio: optional(number()),\n screen_width: optional(number()),\n screen_height: optional(number()),\n screen_resolution: optional(\n pipe(\n string().check(regex(/^\\d+x\\d+$/)),\n transform((v) => v as `${number}x${number}`)\n )\n ),\n webdriver: optional(boolean()),\n release: optional(string()),\n language: optional(string()),\n time_zone: optional(string()),\n page_location: optional(string()),\n page_referrer: optional(string()),\n page_title: optional(string()),\n page_load_id: optional(string()),\n /**\n * @deprecated Renamed to `page_location` in 7.0.0. Accepted so that events from clients\n * still on an older SDK are not stripped of their page URL at this boundary — a browser\n * bundle stays cached long after a backend deploys. Remove once those clients are gone;\n * `pageLocation` in `server/page-location.ts` is the only reader.\n */\n source_url: optional(string()),\n // app info\n advertising_id: optional(string()),\n install_referrer: optional(string()),\n // Ad click ids (URL parameters) and ad platform cookies (underscore names); see AdvertisingInfo.\n // Meta Ads\n fbclid: optional(string()),\n ad_id: optional(string()),\n ad_name: optional(string()),\n adset_id: optional(string()),\n adset_name: optional(string()),\n campaign_id: optional(string()),\n campaign_name: optional(string()),\n placement: optional(string()),\n _fbc: optional(string()),\n _fbp: optional(string()),\n /**\n * @deprecated `fbc` / `fbp` / `rdt_uuid` were renamed to `_fbc` / `_fbp` / `_rdt_uuid` in 9.0.0.\n * Accepted so that conversions from clients still on an older SDK keep their match keys; the\n * senders read them only as a fallback (`server/click-ids.ts`). Remove once those clients are\n * gone.\n */\n fbc: optional(string()),\n fbp: optional(string()),\n rdt_uuid: optional(string()),\n // Google Ads\n gclid: optional(string()),\n gclsrc: optional(string()),\n gad_source: optional(string()),\n gad_campaignid: optional(string()),\n wbraid: optional(string()),\n gbraid: optional(string()),\n dclid: optional(string()),\n _gcl_aw: optional(string()),\n _gcl_gb: optional(string()),\n // Microsoft Ads\n msclkid: optional(string()),\n _uetmsclkid: optional(string()),\n // Reddit Ads\n rdt_cid: optional(string()),\n _rdt_cid: optional(string()),\n _rdt_uuid: optional(string()),\n // LinkedIn Ads\n li_fat_id: optional(string()),\n _li_fat_id: optional(string()),\n // OpenAI Ads\n oppref: optional(string()),\n __oppref: optional(string()),\n __obref: optional(string()),\n // other click ids\n ko_click_id: optional(string()),\n ScCid: optional(string()),\n ttclid: optional(string()),\n twclid: optional(string()),\n yclid: optional(string()),\n epik: optional(string()),\n // utm params\n utm_source: optional(string()),\n utm_medium: optional(string()),\n utm_campaign: optional(string()),\n utm_term: optional(string()),\n utm_content: optional(string()),\n utm_id: optional(string()),\n utm_source_platform: optional(string()),\n utm_creative_format: optional(string()),\n utm_marketing_tactic: optional(string()),\n});\n\nexport const propertiesSchema = optional(\n pipe(\n record(string(), union([propertyText, number(), boolean(), _null(), items])),\n transform(takeProperties)\n )\n);\n\n/** Visitor properties differ from event properties only in taking no nested item lists. */\nconst visitorPropertiesSchema = optional(\n pipe(\n record(string(), union([propertyText, number(), boolean(), _null()])),\n transform(takeProperties)\n )\n);\n\n/**\n * How far an event's time may be from the server's before the client clock it was stamped with is\n * taken as wrong. A batch legitimately arrives late — a tab frozen in the background, a\n * session_start held back after a failed batch — by hours, not days; a phone set to another year\n * writes its sessions into that year.\n */\nconst MAX_CLOCK_SKEW = 24 * 60 * 60 * 1000;\n\n/**\n * Puts the events stamped by a wrong client clock onto the server's, where they are parsed. Only\n * the events outside `MAX_CLOCK_SKEW` move, so one bad event cannot drag the rest of its batch\n * along: they move together by their own latest one — the wrong clock at sending — keeping their\n * order and spacing, and one still out after that (a batch mixing two wrong clocks) is on no clock\n * at all and takes the server's time. Corrected rather than rejected, for the same reason values\n * are truncated: a wrong clock should cost the event its time, not the batch its events.\n */\nfunction alignClock<T extends { timestamp: string }>(events: T[], now = Date.now()): T[] {\n const within = (time: number) => Math.abs(now - time) <= MAX_CLOCK_SKEW;\n const times = events.map((event) => Date.parse(event.timestamp));\n const wrong = times.filter((time) => !within(time));\n if (wrong.length === 0) return events;\n const offset = now - Math.max(...wrong);\n return events.map((event, i) => {\n if (within(times[i])) return event;\n const shifted = times[i] + offset;\n return { ...event, timestamp: new Date(within(shifted) ? shifted : now).toISOString() };\n });\n}\n\nexport const createTrackEventSchema = pipe(\n array(\n object({\n name: string().check(trim(), minLength(1), maxLength(64)),\n visitor_id: uuid(),\n session_id: uuid(),\n platform: _enum(ALL_PLATFORMS),\n environment: _enum(ALL_ENVIRONMENTS),\n timestamp: iso.datetime(),\n tags: tagsSchema,\n properties: propertiesSchema,\n })\n ).check(minLength(1), maxLength(100)),\n transform((events) => alignClock(events))\n);\n\n/**\n * `POST /visitors`, what clients before 11.0 create their visitor with; 11.0 generates the id\n * itself and the server creates the visitor from its first events (README, \"Visitors\").\n * Kept for servers that still serve older clients.\n */\nexport const createVisitorSchema = object({\n device_id: string().check(trim(), minLength(1), maxLength(36)),\n platform: _enum(ALL_PLATFORMS),\n environment: _enum(ALL_ENVIRONMENTS),\n tags: tagsSchema,\n properties: visitorPropertiesSchema,\n});\n\nconst emailValue = pipe(string().check(trim(), toLowerCase(), maxLength(320)), email());\n\n/** E.164: a plus sign (+) prefix, country code, then digits only, no dashes/parens/spaces. */\nconst phoneValue = pipe(string().check(trim()), e164());\n\nconst addressValue = object({\n first_name: optional(string().check(trim(), maxLength(128))),\n last_name: optional(string().check(trim(), maxLength(128))),\n street: optional(string().check(trim(), maxLength(256))),\n city: optional(string().check(trim(), maxLength(128))),\n /** User province, state, or region. Example: `Hampshire` */\n region: optional(string().check(trim(), maxLength(128))),\n postal_code: optional(string().check(trim(), maxLength(32))),\n /** 2-letter country code, per the ISO 3166-1 alpha-2 standard. Example: `UK` */\n country: optional(string().check(trim(), toUpperCase(), regex(/^[A-Z]{2}$/))),\n});\n\n/**\n * User-provided data (UPD) used for enhanced conversions, Customer Match, and demographics.\n * Values are sent unhashed; Google normalizes and hashes them before they reach its servers.\n *\n * Multiple values may be sent to increase the match rate: up to 3 emails, 3 phone numbers, and\n * 2 addresses.\n *\n * @see https://support.google.com/analytics/answer/14078702\n * @see https://support.google.com/google-ads/answer/13258081\n */\nexport const userProvidedDataSchema = object({\n email: optional(union([emailValue, array(emailValue).check(minLength(1), maxLength(3))])),\n phone_number: optional(union([phoneValue, array(phoneValue).check(minLength(1), maxLength(3))])),\n address: optional(union([addressValue, array(addressValue).check(minLength(1), maxLength(2))])),\n});\n\nexport const updateVisitorSchema = object({\n user_id: optional(uuid()),\n user_data: optional(userProvidedDataSchema),\n tags: tagsSchema,\n properties: visitorPropertiesSchema,\n});\n\nexport const createFeedbackSchema = object({\n name: string().check(minLength(1), maxLength(256)),\n email: email().check(maxLength(320)),\n message: string().check(minLength(1), maxLength(65536)),\n});\n\nconst noEmptyString = pipe(\n string().check(maxLength(256)),\n transform((v) => (v ? v : undefined))\n);\n\n/**\n * The schema for creating a link.\n * @see https://support.google.com/analytics/answer/10917952\n * */\nexport const createLinkSchema = object({\n /** The URL that the user is redirected to. */\n url: url().check(minLength(1), maxLength(1024)), // required\n\n /**\n * Campaign ID. Used to identify a specific campaign or promotion. This is a required key for GA4\n * data import. Use the same IDs that you use when uploading campaign cost data.\n */\n utm_id: optional(noEmptyString),\n\n /** Referrer, for example: google, newsletter4, billboard */\n utm_source: string().check(minLength(1), maxLength(256)), // required\n\n /** Marketing medium, for example: cpc, banner, email */\n utm_medium: string().check(minLength(1), maxLength(256)), // required\n\n /** Product, slogan, promo code, for example, spring_sale */\n utm_campaign: string().check(minLength(1), maxLength(256)), // required\n\n /** Paid keyword */\n utm_term: optional(noEmptyString),\n\n /**\n * Use to differentiate creatives. For example, if you have two call-to-action links within the\n * same email message, you can use utm_content and set different values for each so you can tell\n * which version is more effective.\n */\n utm_content: optional(noEmptyString),\n\n /**\n * The platform responsible for directing traffic to a given Analytics property (such as a buying\n * platform that sets budgets and targeting criteria or a platform that manages organic traffic\n * data). For example, Search Ads 360 or Display & Video 360.\n */\n utm_source_platform: optional(noEmptyString),\n\n /**\n * Type of creative, for example, display, native, video, search, utm_creative_format is not\n * currently reported in Google Analytics 4 properties.\n */\n utm_creative_format: optional(noEmptyString),\n\n /**\n * Targeting criteria applied to a campaign, for example, remarketing, prospecting,\n * utm_marketing_tactic is not currently reported in Google Analytics 4 properties.\n * */\n utm_marketing_tactic: optional(noEmptyString),\n});\n\nexport type CreateTrackEventDTO = z.output<typeof createTrackEventSchema>;\nexport type CreateFeedbackDTO = z.output<typeof createFeedbackSchema>;\nexport type CreateLinkDTO = z.output<typeof createLinkSchema>;\nexport type CreateVisitorDTO = z.output<typeof createVisitorSchema>;\nexport type UserProvidedDataDTO = z.output<typeof userProvidedDataSchema>;\nexport type UpdateVisitorDTO = z.output<typeof updateVisitorSchema>;\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["pipe","string","transform","array","record","union","number","boolean","_null","object","optional","trim","minLength","maxLength","regex","uuid","_enum","iso","toLowerCase","email","e164","toUpperCase","url"],"sources":["../../src/schema/index.ts"],"sourcesContent":["import {\n enum as _enum,\n null as _null,\n array,\n boolean,\n e164,\n email,\n iso,\n maxLength,\n minLength,\n number,\n object,\n optional,\n pipe,\n record,\n regex,\n string,\n toLowerCase,\n toUpperCase,\n transform,\n trim,\n union,\n url,\n uuid,\n type z,\n} from 'zod/mini';\nimport type { Environment, Platform } from '../track/types';\n\nconst MAX_KEY_LENGTH = 128;\nconst MAX_VALUE_LENGTH = 512;\nconst MAX_PROPERTIES = 64;\n\n/**\n * Truncated rather than rejected. These schemas validate a whole batch at once, so refusing one\n * oversized value costs every event that traveled with it — and the values that overrun are the\n * ones derived from the page (a link's text, a URL carrying a long query), which no client can\n * bound in advance. A shortened value is worth more than a lost batch.\n */\nconst propertyText = pipe(\n string(),\n transform((value) => value.slice(0, MAX_VALUE_LENGTH))\n);\n\n/**\n * Keys are written by hand in instrumentation code, so an unusable one is a mistake in the host\n * rather than something the visitor typed. It is still dropped rather than rejected, for the same\n * reason: the mistake should cost that property, not the batch it happens to be in. Truncating a\n * key is not an option — two long keys would silently become one field.\n *\n * The key schema below is deliberately permissive so that this transform is reached at all; the\n * trimming it used to do happens here instead. `MAX_PROPERTIES` keeps the first N in insertion\n * order.\n */\nfunction takeProperties<T>(data: Record<string, T>): Record<string, T> {\n const result: Record<string, T> = {};\n let count = 0;\n for (const [rawKey, value] of Object.entries(data)) {\n if (count >= MAX_PROPERTIES) break;\n const key = rawKey.trim();\n if (!key || key.length > MAX_KEY_LENGTH) continue;\n result[key] = value;\n count++;\n }\n return result;\n}\n\n/**\n * Capped at GA4's own item-list limit, and truncated rather than rejected like every other\n * property limit here: an unbounded array is the one field a caller could still blow a batch\n * up with after the value and key limits.\n */\nconst MAX_ITEMS = 200;\n\nconst items = pipe(\n array(\n pipe(\n record(string(), union([propertyText, number(), boolean(), _null()])),\n transform(takeProperties)\n )\n ),\n transform((list) => list.slice(0, MAX_ITEMS))\n);\n\nexport const ALL_PLATFORMS = [\n 'ios',\n 'android',\n 'web',\n 'macos',\n 'windows',\n 'linux',\n 'unknown',\n] as const satisfies Platform[];\n\nexport const ALL_ENVIRONMENTS = ['development', 'production'] as const satisfies Environment[];\n\nexport const tagsSchema = object({\n os: optional(string()),\n os_name: optional(string()),\n os_version: optional(string()),\n browser: optional(string()),\n browser_name: optional(string()),\n browser_version: optional(string()),\n device: optional(string()),\n device_id: optional(string().check(trim(), minLength(1), maxLength(36))),\n device_type: optional(string()),\n device_vendor: optional(string()),\n device_pixel_ratio: optional(number()),\n screen_width: optional(number()),\n screen_height: optional(number()),\n screen_resolution: optional(\n pipe(\n string().check(regex(/^\\d+x\\d+$/)),\n transform((v) => v as `${number}x${number}`)\n )\n ),\n webdriver: optional(boolean()),\n release: optional(string()),\n language: optional(string()),\n time_zone: optional(string()),\n page_location: optional(string()),\n page_referrer: optional(string()),\n page_title: optional(string()),\n page_load_id: optional(string()),\n /**\n * @deprecated Renamed to `page_location` in 7.0.0. Accepted so that events from clients\n * still on an older SDK are not stripped of their page URL at this boundary — a browser\n * bundle stays cached long after a backend deploys. Remove once those clients are gone;\n * `pageLocation` in `server/page-location.ts` is the only reader.\n */\n source_url: optional(string()),\n // app info\n advertising_id: optional(string()),\n install_referrer: optional(string()),\n // Ad click ids (URL parameters) and ad platform cookies (underscore names); see AdvertisingInfo.\n // Meta Ads\n fbclid: optional(string()),\n ad_id: optional(string()),\n ad_name: optional(string()),\n adset_id: optional(string()),\n adset_name: optional(string()),\n campaign_id: optional(string()),\n campaign_name: optional(string()),\n placement: optional(string()),\n _fbc: optional(string()),\n _fbp: optional(string()),\n /**\n * @deprecated `fbc` / `fbp` / `rdt_uuid` were renamed to `_fbc` / `_fbp` / `_rdt_uuid` in 9.0.0.\n * Accepted so that conversions from clients still on an older SDK keep their match keys; the\n * senders read them only as a fallback (`server/click-ids.ts`). Remove once those clients are\n * gone.\n */\n fbc: optional(string()),\n fbp: optional(string()),\n rdt_uuid: optional(string()),\n // Google Ads\n gclid: optional(string()),\n gclsrc: optional(string()),\n gad_source: optional(string()),\n gad_campaignid: optional(string()),\n wbraid: optional(string()),\n gbraid: optional(string()),\n dclid: optional(string()),\n _gcl_aw: optional(string()),\n _gcl_gb: optional(string()),\n // Microsoft Ads\n msclkid: optional(string()),\n _uetmsclkid: optional(string()),\n // Reddit Ads\n rdt_cid: optional(string()),\n _rdt_cid: optional(string()),\n _rdt_uuid: optional(string()),\n // LinkedIn Ads\n li_fat_id: optional(string()),\n _li_fat_id: optional(string()),\n // OpenAI Ads\n oppref: optional(string()),\n __oppref: optional(string()),\n __obref: optional(string()),\n // other click ids\n ko_click_id: optional(string()),\n ScCid: optional(string()),\n ttclid: optional(string()),\n twclid: optional(string()),\n yclid: optional(string()),\n epik: optional(string()),\n // utm params\n utm_source: optional(string()),\n utm_medium: optional(string()),\n utm_campaign: optional(string()),\n utm_term: optional(string()),\n utm_content: optional(string()),\n utm_id: optional(string()),\n utm_source_platform: optional(string()),\n utm_creative_format: optional(string()),\n utm_marketing_tactic: optional(string()),\n});\n\nexport const propertiesSchema = optional(\n pipe(\n record(string(), union([propertyText, number(), boolean(), _null(), items])),\n transform(takeProperties)\n )\n);\n\n/**\n * How far an event's time may be from the server's before the client clock it was stamped with is\n * taken as wrong. A batch legitimately arrives late — a tab frozen in the background, a\n * session_start held back after a failed batch — by hours, not days; a phone set to another year\n * writes its sessions into that year.\n */\nconst MAX_CLOCK_SKEW = 24 * 60 * 60 * 1000;\n\n/**\n * Puts the events stamped by a wrong client clock onto the server's, where they are parsed. Only\n * the events outside `MAX_CLOCK_SKEW` move, so one bad event cannot drag the rest of its batch\n * along: they move together by their own latest one — the wrong clock at sending — keeping their\n * order and spacing, and one still out after that (a batch mixing two wrong clocks) is on no clock\n * at all and takes the server's time. Corrected rather than rejected, for the same reason values\n * are truncated: a wrong clock should cost the event its time, not the batch its events.\n */\nfunction alignClock<T extends { timestamp: string }>(events: T[], now = Date.now()): T[] {\n const within = (time: number) => Math.abs(now - time) <= MAX_CLOCK_SKEW;\n const times = events.map((event) => Date.parse(event.timestamp));\n const wrong = times.filter((time) => !within(time));\n if (wrong.length === 0) return events;\n const offset = now - Math.max(...wrong);\n return events.map((event, i) => {\n if (within(times[i])) return event;\n const shifted = times[i] + offset;\n return { ...event, timestamp: new Date(within(shifted) ? shifted : now).toISOString() };\n });\n}\n\nexport const createTrackEventSchema = pipe(\n array(\n object({\n name: string().check(trim(), minLength(1), maxLength(64)),\n visitor_id: uuid(),\n session_id: uuid(),\n platform: _enum(ALL_PLATFORMS),\n environment: _enum(ALL_ENVIRONMENTS),\n timestamp: iso.datetime(),\n tags: tagsSchema,\n properties: propertiesSchema,\n })\n ).check(minLength(1), maxLength(100)),\n transform((events) => alignClock(events))\n);\n\n/**\n * `POST /visitors`, what clients before 11.0 create their visitor with; 11.0 generates the id\n * itself and the server creates the visitor from its first events (README, \"Visitors\").\n * Kept for servers that still serve older clients.\n */\nexport const createVisitorSchema = object({\n device_id: string().check(trim(), minLength(1), maxLength(36)),\n platform: _enum(ALL_PLATFORMS),\n environment: _enum(ALL_ENVIRONMENTS),\n tags: tagsSchema,\n});\n\nconst emailValue = pipe(string().check(trim(), toLowerCase(), maxLength(320)), email());\n\n/** E.164: a plus sign (+) prefix, country code, then digits only, no dashes/parens/spaces. */\nconst phoneValue = pipe(string().check(trim()), e164());\n\nconst addressValue = object({\n first_name: optional(string().check(trim(), maxLength(128))),\n last_name: optional(string().check(trim(), maxLength(128))),\n street: optional(string().check(trim(), maxLength(256))),\n city: optional(string().check(trim(), maxLength(128))),\n /** User province, state, or region. Example: `Hampshire` */\n region: optional(string().check(trim(), maxLength(128))),\n postal_code: optional(string().check(trim(), maxLength(32))),\n /** 2-letter country code, per the ISO 3166-1 alpha-2 standard. Example: `UK` */\n country: optional(string().check(trim(), toUpperCase(), regex(/^[A-Z]{2}$/))),\n});\n\n/**\n * User-provided data (UPD) used for enhanced conversions, Customer Match, and demographics.\n * Values are sent unhashed; Google normalizes and hashes them before they reach its servers.\n *\n * Multiple values may be sent to increase the match rate: up to 3 emails, 3 phone numbers, and\n * 2 addresses.\n *\n * @see https://support.google.com/analytics/answer/14078702\n * @see https://support.google.com/google-ads/answer/13258081\n */\nexport const userProvidedDataSchema = object({\n email: optional(union([emailValue, array(emailValue).check(minLength(1), maxLength(3))])),\n phone_number: optional(union([phoneValue, array(phoneValue).check(minLength(1), maxLength(3))])),\n address: optional(union([addressValue, array(addressValue).check(minLength(1), maxLength(2))])),\n});\n\nexport const updateVisitorSchema = object({\n user_id: optional(uuid()),\n user_data: optional(userProvidedDataSchema),\n /**\n * Sent by clients before 11.1, which PATCHed their tags on every page load. From 11.1 the\n * server refreshes `visitor.tags` from each `session_start` — the moment the visit arrives —\n * and `setVisitor` sends none: at sign-in the page is no longer where the visit came in.\n */\n tags: optional(tagsSchema),\n});\n\nexport const createFeedbackSchema = object({\n name: string().check(minLength(1), maxLength(256)),\n email: email().check(maxLength(320)),\n message: string().check(minLength(1), maxLength(65536)),\n});\n\nconst noEmptyString = pipe(\n string().check(maxLength(256)),\n transform((v) => (v ? v : undefined))\n);\n\n/**\n * The schema for creating a link.\n * @see https://support.google.com/analytics/answer/10917952\n * */\nexport const createLinkSchema = object({\n /** The URL that the user is redirected to. */\n url: url().check(minLength(1), maxLength(1024)), // required\n\n /**\n * Campaign ID. Used to identify a specific campaign or promotion. This is a required key for GA4\n * data import. Use the same IDs that you use when uploading campaign cost data.\n */\n utm_id: optional(noEmptyString),\n\n /** Referrer, for example: google, newsletter4, billboard */\n utm_source: string().check(minLength(1), maxLength(256)), // required\n\n /** Marketing medium, for example: cpc, banner, email */\n utm_medium: string().check(minLength(1), maxLength(256)), // required\n\n /** Product, slogan, promo code, for example, spring_sale */\n utm_campaign: string().check(minLength(1), maxLength(256)), // required\n\n /** Paid keyword */\n utm_term: optional(noEmptyString),\n\n /**\n * Use to differentiate creatives. For example, if you have two call-to-action links within the\n * same email message, you can use utm_content and set different values for each so you can tell\n * which version is more effective.\n */\n utm_content: optional(noEmptyString),\n\n /**\n * The platform responsible for directing traffic to a given Analytics property (such as a buying\n * platform that sets budgets and targeting criteria or a platform that manages organic traffic\n * data). For example, Search Ads 360 or Display & Video 360.\n */\n utm_source_platform: optional(noEmptyString),\n\n /**\n * Type of creative, for example, display, native, video, search, utm_creative_format is not\n * currently reported in Google Analytics 4 properties.\n */\n utm_creative_format: optional(noEmptyString),\n\n /**\n * Targeting criteria applied to a campaign, for example, remarketing, prospecting,\n * utm_marketing_tactic is not currently reported in Google Analytics 4 properties.\n * */\n utm_marketing_tactic: optional(noEmptyString),\n});\n\nexport type CreateTrackEventDTO = z.output<typeof createTrackEventSchema>;\nexport type CreateFeedbackDTO = z.output<typeof createFeedbackSchema>;\nexport type CreateLinkDTO = z.output<typeof createLinkSchema>;\nexport type CreateVisitorDTO = z.output<typeof createVisitorSchema>;\nexport type UserProvidedDataDTO = z.output<typeof userProvidedDataSchema>;\nexport type UpdateVisitorDTO = z.output<typeof updateVisitorSchema>;\n"],"mappings":"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"}
@@ -429,7 +429,6 @@ export declare const createVisitorSchema: z.ZodMiniObject<{
429
429
  utm_creative_format: z.ZodMiniOptional<z.ZodMiniString<string>>;
430
430
  utm_marketing_tactic: z.ZodMiniOptional<z.ZodMiniString<string>>;
431
431
  }, z.core.$strip>;
432
- properties: z.ZodMiniOptional<z.ZodMiniPipe<z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniUnion<readonly [z.ZodMiniPipe<z.ZodMiniString<string>, z.ZodMiniTransform<string, string>>, z.ZodMiniNumber<number>, z.ZodMiniBoolean<boolean>, z.ZodMiniNull]>>, z.ZodMiniTransform<Record<string, string | number | boolean | null>, Record<string, string | number | boolean | null>>>>;
433
432
  }, z.core.$strip>;
434
433
  /**
435
434
  * User-provided data (UPD) used for enhanced conversions, Customer Match, and demographics.
@@ -485,7 +484,7 @@ export declare const updateVisitorSchema: z.ZodMiniObject<{
485
484
  country: z.ZodMiniOptional<z.ZodMiniString<string>>;
486
485
  }, z.core.$strip>>]>>;
487
486
  }, z.core.$strip>>;
488
- tags: z.ZodMiniObject<{
487
+ tags: z.ZodMiniOptional<z.ZodMiniObject<{
489
488
  os: z.ZodMiniOptional<z.ZodMiniString<string>>;
490
489
  os_name: z.ZodMiniOptional<z.ZodMiniString<string>>;
491
490
  os_version: z.ZodMiniOptional<z.ZodMiniString<string>>;
@@ -558,8 +557,7 @@ export declare const updateVisitorSchema: z.ZodMiniObject<{
558
557
  utm_source_platform: z.ZodMiniOptional<z.ZodMiniString<string>>;
559
558
  utm_creative_format: z.ZodMiniOptional<z.ZodMiniString<string>>;
560
559
  utm_marketing_tactic: z.ZodMiniOptional<z.ZodMiniString<string>>;
561
- }, z.core.$strip>;
562
- properties: z.ZodMiniOptional<z.ZodMiniPipe<z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniUnion<readonly [z.ZodMiniPipe<z.ZodMiniString<string>, z.ZodMiniTransform<string, string>>, z.ZodMiniNumber<number>, z.ZodMiniBoolean<boolean>, z.ZodMiniNull]>>, z.ZodMiniTransform<Record<string, string | number | boolean | null>, Record<string, string | number | boolean | null>>>>;
560
+ }, z.core.$strip>>;
563
561
  }, z.core.$strip>;
564
562
  export declare const createFeedbackSchema: z.ZodMiniObject<{
565
563
  name: z.ZodMiniString<string>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/schema/index.ts"],"mappings":";;qBAmFa;qBAUA;qBAEA,YAAU,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoGrB,EAAA,KAAA;qBAEW,kBAAgB,EAAA,gBAAA,EAAA,YAAA,EAAA,cAAA,EAAA,uBAAA,EAAA,uBAAA,EAAA,YAAA,EAAA,uBAAA,EAAA,mCAAA,EAAA,uBAAA,EAAA,yBAAA,EAAA,aAAA,EAAA,YAAA,EAAA,aAAA,EAAA,YAAA,EAAA,cAAA,EAAA,uBAAA,EAAA,uBAAA,EAAA,YAAA,EAAA,uBAAA,EAAA,mCAAA,EAAA,uBAAA,EAAA,yBAAA,EAAA,gBAAA,EAAA,iBAAA,kDAAA,qDAAA,EAAA,iBAAA,oDAAA,yDAAA,EAAA,iBAAA,2CAAA,4DAAA,2CAAA;qBA4ChB,wBAAsB,EAAA,YAAA,EAAA,aAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAqBtB,qBAAmB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAM9B,EAAA,KAAA;;;;;;;;;;;qBA6BW,wBAAsB,EAAA;;;;;;;;;;;;;;;;;;;;GAIjC,EAAA,KAAA;qBAEW,qBAAmB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAK9B,EAAA,KAAA;qBAEW,sBAAoB,EAAA;;;;GAI/B,EAAA,KAAA;;;;;qBAWW,kBAAgB,EAAA;;;;;;;;;;;GA+C3B,EAAA,KAAA;YAEU,sBAAsB,EAAE,cAAc;YACtC,oBAAoB,EAAE,cAAc;YACpC,gBAAgB,EAAE,cAAc;YAChC,mBAAmB,EAAE,cAAc;YACnC,sBAAsB,EAAE,cAAc;YACtC,mBAAmB,EAAE,cAAc"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/schema/index.ts"],"mappings":";;qBAmFa;qBAUA;qBAEA,YAAU,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoGrB,EAAA,KAAA;qBAEW,kBAAgB,EAAA,gBAAA,EAAA,YAAA,EAAA,cAAA,EAAA,uBAAA,EAAA,uBAAA,EAAA,YAAA,EAAA,uBAAA,EAAA,mCAAA,EAAA,uBAAA,EAAA,yBAAA,EAAA,aAAA,EAAA,YAAA,EAAA,aAAA,EAAA,YAAA,EAAA,cAAA,EAAA,uBAAA,EAAA,uBAAA,EAAA,YAAA,EAAA,uBAAA,EAAA,mCAAA,EAAA,uBAAA,EAAA,yBAAA,EAAA,gBAAA,EAAA,iBAAA,kDAAA,qDAAA,EAAA,iBAAA,oDAAA,yDAAA,EAAA,iBAAA,2CAAA,4DAAA,2CAAA;qBAoChB,wBAAsB,EAAA,YAAA,EAAA,aAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAqBtB,qBAAmB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAK9B,EAAA,KAAA;;;;;;;;;;;qBA6BW,wBAAsB,EAAA;;;;;;;;;;;;;;;;;;;;GAIjC,EAAA,KAAA;qBAEW,qBAAmB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAS9B,EAAA,KAAA;qBAEW,sBAAoB,EAAA;;;;GAI/B,EAAA,KAAA;;;;;qBAWW,kBAAgB,EAAA;;;;;;;;;;;GA+C3B,EAAA,KAAA;YAEU,sBAAsB,EAAE,cAAc;YACtC,oBAAoB,EAAE,cAAc;YACpC,gBAAgB,EAAE,cAAc;YAChC,mBAAmB,EAAE,cAAc;YACnC,sBAAsB,EAAE,cAAc;YACtC,mBAAmB,EAAE,cAAc"}
@@ -429,7 +429,6 @@ export declare const createVisitorSchema: z.ZodMiniObject<{
429
429
  utm_creative_format: z.ZodMiniOptional<z.ZodMiniString<string>>;
430
430
  utm_marketing_tactic: z.ZodMiniOptional<z.ZodMiniString<string>>;
431
431
  }, z.core.$strip>;
432
- properties: z.ZodMiniOptional<z.ZodMiniPipe<z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniUnion<readonly [z.ZodMiniPipe<z.ZodMiniString<string>, z.ZodMiniTransform<string, string>>, z.ZodMiniNumber<number>, z.ZodMiniBoolean<boolean>, z.ZodMiniNull]>>, z.ZodMiniTransform<Record<string, string | number | boolean | null>, Record<string, string | number | boolean | null>>>>;
433
432
  }, z.core.$strip>;
434
433
  /**
435
434
  * User-provided data (UPD) used for enhanced conversions, Customer Match, and demographics.
@@ -485,7 +484,7 @@ export declare const updateVisitorSchema: z.ZodMiniObject<{
485
484
  country: z.ZodMiniOptional<z.ZodMiniString<string>>;
486
485
  }, z.core.$strip>>]>>;
487
486
  }, z.core.$strip>>;
488
- tags: z.ZodMiniObject<{
487
+ tags: z.ZodMiniOptional<z.ZodMiniObject<{
489
488
  os: z.ZodMiniOptional<z.ZodMiniString<string>>;
490
489
  os_name: z.ZodMiniOptional<z.ZodMiniString<string>>;
491
490
  os_version: z.ZodMiniOptional<z.ZodMiniString<string>>;
@@ -558,8 +557,7 @@ export declare const updateVisitorSchema: z.ZodMiniObject<{
558
557
  utm_source_platform: z.ZodMiniOptional<z.ZodMiniString<string>>;
559
558
  utm_creative_format: z.ZodMiniOptional<z.ZodMiniString<string>>;
560
559
  utm_marketing_tactic: z.ZodMiniOptional<z.ZodMiniString<string>>;
561
- }, z.core.$strip>;
562
- properties: z.ZodMiniOptional<z.ZodMiniPipe<z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniUnion<readonly [z.ZodMiniPipe<z.ZodMiniString<string>, z.ZodMiniTransform<string, string>>, z.ZodMiniNumber<number>, z.ZodMiniBoolean<boolean>, z.ZodMiniNull]>>, z.ZodMiniTransform<Record<string, string | number | boolean | null>, Record<string, string | number | boolean | null>>>>;
560
+ }, z.core.$strip>>;
563
561
  }, z.core.$strip>;
564
562
  export declare const createFeedbackSchema: z.ZodMiniObject<{
565
563
  name: z.ZodMiniString<string>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/schema/index.ts"],"mappings":";;qBAmFa;qBAUA;qBAEA,YAAU,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoGrB,EAAA,KAAA;qBAEW,kBAAgB,EAAA,gBAAA,EAAA,YAAA,EAAA,cAAA,EAAA,uBAAA,EAAA,uBAAA,EAAA,YAAA,EAAA,uBAAA,EAAA,mCAAA,EAAA,uBAAA,EAAA,yBAAA,EAAA,aAAA,EAAA,YAAA,EAAA,aAAA,EAAA,YAAA,EAAA,cAAA,EAAA,uBAAA,EAAA,uBAAA,EAAA,YAAA,EAAA,uBAAA,EAAA,mCAAA,EAAA,uBAAA,EAAA,yBAAA,EAAA,gBAAA,EAAA,iBAAA,kDAAA,qDAAA,EAAA,iBAAA,oDAAA,yDAAA,EAAA,iBAAA,2CAAA,4DAAA,2CAAA;qBA4ChB,wBAAsB,EAAA,YAAA,EAAA,aAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAqBtB,qBAAmB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAM9B,EAAA,KAAA;;;;;;;;;;;qBA6BW,wBAAsB,EAAA;;;;;;;;;;;;;;;;;;;;GAIjC,EAAA,KAAA;qBAEW,qBAAmB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAK9B,EAAA,KAAA;qBAEW,sBAAoB,EAAA;;;;GAI/B,EAAA,KAAA;;;;;qBAWW,kBAAgB,EAAA;;;;;;;;;;;GA+C3B,EAAA,KAAA;YAEU,sBAAsB,EAAE,cAAc;YACtC,oBAAoB,EAAE,cAAc;YACpC,gBAAgB,EAAE,cAAc;YAChC,mBAAmB,EAAE,cAAc;YACnC,sBAAsB,EAAE,cAAc;YACtC,mBAAmB,EAAE,cAAc"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/schema/index.ts"],"mappings":";;qBAmFa;qBAUA;qBAEA,YAAU,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoGrB,EAAA,KAAA;qBAEW,kBAAgB,EAAA,gBAAA,EAAA,YAAA,EAAA,cAAA,EAAA,uBAAA,EAAA,uBAAA,EAAA,YAAA,EAAA,uBAAA,EAAA,mCAAA,EAAA,uBAAA,EAAA,yBAAA,EAAA,aAAA,EAAA,YAAA,EAAA,aAAA,EAAA,YAAA,EAAA,cAAA,EAAA,uBAAA,EAAA,uBAAA,EAAA,YAAA,EAAA,uBAAA,EAAA,mCAAA,EAAA,uBAAA,EAAA,yBAAA,EAAA,gBAAA,EAAA,iBAAA,kDAAA,qDAAA,EAAA,iBAAA,oDAAA,yDAAA,EAAA,iBAAA,2CAAA,4DAAA,2CAAA;qBAoChB,wBAAsB,EAAA,YAAA,EAAA,aAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAqBtB,qBAAmB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAK9B,EAAA,KAAA;;;;;;;;;;;qBA6BW,wBAAsB,EAAA;;;;;;;;;;;;;;;;;;;;GAIjC,EAAA,KAAA;qBAEW,qBAAmB,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAS9B,EAAA,KAAA;qBAEW,sBAAoB,EAAA;;;;GAI/B,EAAA,KAAA;;;;;qBAWW,kBAAgB,EAAA;;;;;;;;;;;GA+C3B,EAAA,KAAA;YAEU,sBAAsB,EAAE,cAAc;YACtC,oBAAoB,EAAE,cAAc;YACpC,gBAAgB,EAAE,cAAc;YAChC,mBAAmB,EAAE,cAAc;YACnC,sBAAsB,EAAE,cAAc;YACtC,mBAAmB,EAAE,cAAc"}
@@ -147,13 +147,6 @@ const propertiesSchema = optional(pipe(record(string(), union([
147
147
  null$1(),
148
148
  items
149
149
  ])), transform(takeProperties)));
150
- /** Visitor properties differ from event properties only in taking no nested item lists. */
151
- const visitorPropertiesSchema = optional(pipe(record(string(), union([
152
- propertyText,
153
- number(),
154
- boolean(),
155
- null$1()
156
- ])), transform(takeProperties)));
157
150
  /**
158
151
  * How far an event's time may be from the server's before the client clock it was stamped with is
159
152
  * taken as wrong. A batch legitimately arrives late — a tab frozen in the background, a
@@ -203,8 +196,7 @@ const createVisitorSchema = object({
203
196
  device_id: string().check(trim(), minLength(1), maxLength(36)),
204
197
  platform: enum$1(ALL_PLATFORMS),
205
198
  environment: enum$1(ALL_ENVIRONMENTS),
206
- tags: tagsSchema,
207
- properties: visitorPropertiesSchema
199
+ tags: tagsSchema
208
200
  });
209
201
  const emailValue = pipe(string().check(trim(), toLowerCase(), maxLength(320)), email());
210
202
  /** E.164: a plus sign (+) prefix, country code, then digits only, no dashes/parens/spaces. */
@@ -238,8 +230,12 @@ const userProvidedDataSchema = object({
238
230
  const updateVisitorSchema = object({
239
231
  user_id: optional(uuid()),
240
232
  user_data: optional(userProvidedDataSchema),
241
- tags: tagsSchema,
242
- properties: visitorPropertiesSchema
233
+ /**
234
+ * Sent by clients before 11.1, which PATCHed their tags on every page load. From 11.1 the
235
+ * server refreshes `visitor.tags` from each `session_start` — the moment the visit arrives —
236
+ * and `setVisitor` sends none: at sign-in the page is no longer where the visit came in.
237
+ */
238
+ tags: optional(tagsSchema)
243
239
  });
244
240
  const createFeedbackSchema = object({
245
241
  name: string().check(minLength(1), maxLength(256)),
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["_null","_enum"],"sources":["../../src/schema/index.ts"],"sourcesContent":["import {\n enum as _enum,\n null as _null,\n array,\n boolean,\n e164,\n email,\n iso,\n maxLength,\n minLength,\n number,\n object,\n optional,\n pipe,\n record,\n regex,\n string,\n toLowerCase,\n toUpperCase,\n transform,\n trim,\n union,\n url,\n uuid,\n type z,\n} from 'zod/mini';\nimport type { Environment, Platform } from '../track/types';\n\nconst MAX_KEY_LENGTH = 128;\nconst MAX_VALUE_LENGTH = 512;\nconst MAX_PROPERTIES = 64;\n\n/**\n * Truncated rather than rejected. These schemas validate a whole batch at once, so refusing one\n * oversized value costs every event that traveled with it — and the values that overrun are the\n * ones derived from the page (a link's text, a URL carrying a long query), which no client can\n * bound in advance. A shortened value is worth more than a lost batch.\n */\nconst propertyText = pipe(\n string(),\n transform((value) => value.slice(0, MAX_VALUE_LENGTH))\n);\n\n/**\n * Keys are written by hand in instrumentation code, so an unusable one is a mistake in the host\n * rather than something the visitor typed. It is still dropped rather than rejected, for the same\n * reason: the mistake should cost that property, not the batch it happens to be in. Truncating a\n * key is not an option — two long keys would silently become one field.\n *\n * The key schema below is deliberately permissive so that this transform is reached at all; the\n * trimming it used to do happens here instead. `MAX_PROPERTIES` keeps the first N in insertion\n * order.\n */\nfunction takeProperties<T>(data: Record<string, T>): Record<string, T> {\n const result: Record<string, T> = {};\n let count = 0;\n for (const [rawKey, value] of Object.entries(data)) {\n if (count >= MAX_PROPERTIES) break;\n const key = rawKey.trim();\n if (!key || key.length > MAX_KEY_LENGTH) continue;\n result[key] = value;\n count++;\n }\n return result;\n}\n\n/**\n * Capped at GA4's own item-list limit, and truncated rather than rejected like every other\n * property limit here: an unbounded array is the one field a caller could still blow a batch\n * up with after the value and key limits.\n */\nconst MAX_ITEMS = 200;\n\nconst items = pipe(\n array(\n pipe(\n record(string(), union([propertyText, number(), boolean(), _null()])),\n transform(takeProperties)\n )\n ),\n transform((list) => list.slice(0, MAX_ITEMS))\n);\n\nexport const ALL_PLATFORMS = [\n 'ios',\n 'android',\n 'web',\n 'macos',\n 'windows',\n 'linux',\n 'unknown',\n] as const satisfies Platform[];\n\nexport const ALL_ENVIRONMENTS = ['development', 'production'] as const satisfies Environment[];\n\nexport const tagsSchema = object({\n os: optional(string()),\n os_name: optional(string()),\n os_version: optional(string()),\n browser: optional(string()),\n browser_name: optional(string()),\n browser_version: optional(string()),\n device: optional(string()),\n device_id: optional(string().check(trim(), minLength(1), maxLength(36))),\n device_type: optional(string()),\n device_vendor: optional(string()),\n device_pixel_ratio: optional(number()),\n screen_width: optional(number()),\n screen_height: optional(number()),\n screen_resolution: optional(\n pipe(\n string().check(regex(/^\\d+x\\d+$/)),\n transform((v) => v as `${number}x${number}`)\n )\n ),\n webdriver: optional(boolean()),\n release: optional(string()),\n language: optional(string()),\n time_zone: optional(string()),\n page_location: optional(string()),\n page_referrer: optional(string()),\n page_title: optional(string()),\n page_load_id: optional(string()),\n /**\n * @deprecated Renamed to `page_location` in 7.0.0. Accepted so that events from clients\n * still on an older SDK are not stripped of their page URL at this boundary — a browser\n * bundle stays cached long after a backend deploys. Remove once those clients are gone;\n * `pageLocation` in `server/page-location.ts` is the only reader.\n */\n source_url: optional(string()),\n // app info\n advertising_id: optional(string()),\n install_referrer: optional(string()),\n // Ad click ids (URL parameters) and ad platform cookies (underscore names); see AdvertisingInfo.\n // Meta Ads\n fbclid: optional(string()),\n ad_id: optional(string()),\n ad_name: optional(string()),\n adset_id: optional(string()),\n adset_name: optional(string()),\n campaign_id: optional(string()),\n campaign_name: optional(string()),\n placement: optional(string()),\n _fbc: optional(string()),\n _fbp: optional(string()),\n /**\n * @deprecated `fbc` / `fbp` / `rdt_uuid` were renamed to `_fbc` / `_fbp` / `_rdt_uuid` in 9.0.0.\n * Accepted so that conversions from clients still on an older SDK keep their match keys; the\n * senders read them only as a fallback (`server/click-ids.ts`). Remove once those clients are\n * gone.\n */\n fbc: optional(string()),\n fbp: optional(string()),\n rdt_uuid: optional(string()),\n // Google Ads\n gclid: optional(string()),\n gclsrc: optional(string()),\n gad_source: optional(string()),\n gad_campaignid: optional(string()),\n wbraid: optional(string()),\n gbraid: optional(string()),\n dclid: optional(string()),\n _gcl_aw: optional(string()),\n _gcl_gb: optional(string()),\n // Microsoft Ads\n msclkid: optional(string()),\n _uetmsclkid: optional(string()),\n // Reddit Ads\n rdt_cid: optional(string()),\n _rdt_cid: optional(string()),\n _rdt_uuid: optional(string()),\n // LinkedIn Ads\n li_fat_id: optional(string()),\n _li_fat_id: optional(string()),\n // OpenAI Ads\n oppref: optional(string()),\n __oppref: optional(string()),\n __obref: optional(string()),\n // other click ids\n ko_click_id: optional(string()),\n ScCid: optional(string()),\n ttclid: optional(string()),\n twclid: optional(string()),\n yclid: optional(string()),\n epik: optional(string()),\n // utm params\n utm_source: optional(string()),\n utm_medium: optional(string()),\n utm_campaign: optional(string()),\n utm_term: optional(string()),\n utm_content: optional(string()),\n utm_id: optional(string()),\n utm_source_platform: optional(string()),\n utm_creative_format: optional(string()),\n utm_marketing_tactic: optional(string()),\n});\n\nexport const propertiesSchema = optional(\n pipe(\n record(string(), union([propertyText, number(), boolean(), _null(), items])),\n transform(takeProperties)\n )\n);\n\n/** Visitor properties differ from event properties only in taking no nested item lists. */\nconst visitorPropertiesSchema = optional(\n pipe(\n record(string(), union([propertyText, number(), boolean(), _null()])),\n transform(takeProperties)\n )\n);\n\n/**\n * How far an event's time may be from the server's before the client clock it was stamped with is\n * taken as wrong. A batch legitimately arrives late — a tab frozen in the background, a\n * session_start held back after a failed batch — by hours, not days; a phone set to another year\n * writes its sessions into that year.\n */\nconst MAX_CLOCK_SKEW = 24 * 60 * 60 * 1000;\n\n/**\n * Puts the events stamped by a wrong client clock onto the server's, where they are parsed. Only\n * the events outside `MAX_CLOCK_SKEW` move, so one bad event cannot drag the rest of its batch\n * along: they move together by their own latest one — the wrong clock at sending — keeping their\n * order and spacing, and one still out after that (a batch mixing two wrong clocks) is on no clock\n * at all and takes the server's time. Corrected rather than rejected, for the same reason values\n * are truncated: a wrong clock should cost the event its time, not the batch its events.\n */\nfunction alignClock<T extends { timestamp: string }>(events: T[], now = Date.now()): T[] {\n const within = (time: number) => Math.abs(now - time) <= MAX_CLOCK_SKEW;\n const times = events.map((event) => Date.parse(event.timestamp));\n const wrong = times.filter((time) => !within(time));\n if (wrong.length === 0) return events;\n const offset = now - Math.max(...wrong);\n return events.map((event, i) => {\n if (within(times[i])) return event;\n const shifted = times[i] + offset;\n return { ...event, timestamp: new Date(within(shifted) ? shifted : now).toISOString() };\n });\n}\n\nexport const createTrackEventSchema = pipe(\n array(\n object({\n name: string().check(trim(), minLength(1), maxLength(64)),\n visitor_id: uuid(),\n session_id: uuid(),\n platform: _enum(ALL_PLATFORMS),\n environment: _enum(ALL_ENVIRONMENTS),\n timestamp: iso.datetime(),\n tags: tagsSchema,\n properties: propertiesSchema,\n })\n ).check(minLength(1), maxLength(100)),\n transform((events) => alignClock(events))\n);\n\n/**\n * `POST /visitors`, what clients before 11.0 create their visitor with; 11.0 generates the id\n * itself and the server creates the visitor from its first events (README, \"Visitors\").\n * Kept for servers that still serve older clients.\n */\nexport const createVisitorSchema = object({\n device_id: string().check(trim(), minLength(1), maxLength(36)),\n platform: _enum(ALL_PLATFORMS),\n environment: _enum(ALL_ENVIRONMENTS),\n tags: tagsSchema,\n properties: visitorPropertiesSchema,\n});\n\nconst emailValue = pipe(string().check(trim(), toLowerCase(), maxLength(320)), email());\n\n/** E.164: a plus sign (+) prefix, country code, then digits only, no dashes/parens/spaces. */\nconst phoneValue = pipe(string().check(trim()), e164());\n\nconst addressValue = object({\n first_name: optional(string().check(trim(), maxLength(128))),\n last_name: optional(string().check(trim(), maxLength(128))),\n street: optional(string().check(trim(), maxLength(256))),\n city: optional(string().check(trim(), maxLength(128))),\n /** User province, state, or region. Example: `Hampshire` */\n region: optional(string().check(trim(), maxLength(128))),\n postal_code: optional(string().check(trim(), maxLength(32))),\n /** 2-letter country code, per the ISO 3166-1 alpha-2 standard. Example: `UK` */\n country: optional(string().check(trim(), toUpperCase(), regex(/^[A-Z]{2}$/))),\n});\n\n/**\n * User-provided data (UPD) used for enhanced conversions, Customer Match, and demographics.\n * Values are sent unhashed; Google normalizes and hashes them before they reach its servers.\n *\n * Multiple values may be sent to increase the match rate: up to 3 emails, 3 phone numbers, and\n * 2 addresses.\n *\n * @see https://support.google.com/analytics/answer/14078702\n * @see https://support.google.com/google-ads/answer/13258081\n */\nexport const userProvidedDataSchema = object({\n email: optional(union([emailValue, array(emailValue).check(minLength(1), maxLength(3))])),\n phone_number: optional(union([phoneValue, array(phoneValue).check(minLength(1), maxLength(3))])),\n address: optional(union([addressValue, array(addressValue).check(minLength(1), maxLength(2))])),\n});\n\nexport const updateVisitorSchema = object({\n user_id: optional(uuid()),\n user_data: optional(userProvidedDataSchema),\n tags: tagsSchema,\n properties: visitorPropertiesSchema,\n});\n\nexport const createFeedbackSchema = object({\n name: string().check(minLength(1), maxLength(256)),\n email: email().check(maxLength(320)),\n message: string().check(minLength(1), maxLength(65536)),\n});\n\nconst noEmptyString = pipe(\n string().check(maxLength(256)),\n transform((v) => (v ? v : undefined))\n);\n\n/**\n * The schema for creating a link.\n * @see https://support.google.com/analytics/answer/10917952\n * */\nexport const createLinkSchema = object({\n /** The URL that the user is redirected to. */\n url: url().check(minLength(1), maxLength(1024)), // required\n\n /**\n * Campaign ID. Used to identify a specific campaign or promotion. This is a required key for GA4\n * data import. Use the same IDs that you use when uploading campaign cost data.\n */\n utm_id: optional(noEmptyString),\n\n /** Referrer, for example: google, newsletter4, billboard */\n utm_source: string().check(minLength(1), maxLength(256)), // required\n\n /** Marketing medium, for example: cpc, banner, email */\n utm_medium: string().check(minLength(1), maxLength(256)), // required\n\n /** Product, slogan, promo code, for example, spring_sale */\n utm_campaign: string().check(minLength(1), maxLength(256)), // required\n\n /** Paid keyword */\n utm_term: optional(noEmptyString),\n\n /**\n * Use to differentiate creatives. For example, if you have two call-to-action links within the\n * same email message, you can use utm_content and set different values for each so you can tell\n * which version is more effective.\n */\n utm_content: optional(noEmptyString),\n\n /**\n * The platform responsible for directing traffic to a given Analytics property (such as a buying\n * platform that sets budgets and targeting criteria or a platform that manages organic traffic\n * data). For example, Search Ads 360 or Display & Video 360.\n */\n utm_source_platform: optional(noEmptyString),\n\n /**\n * Type of creative, for example, display, native, video, search, utm_creative_format is not\n * currently reported in Google Analytics 4 properties.\n */\n utm_creative_format: optional(noEmptyString),\n\n /**\n * Targeting criteria applied to a campaign, for example, remarketing, prospecting,\n * utm_marketing_tactic is not currently reported in Google Analytics 4 properties.\n * */\n utm_marketing_tactic: optional(noEmptyString),\n});\n\nexport type CreateTrackEventDTO = z.output<typeof createTrackEventSchema>;\nexport type CreateFeedbackDTO = z.output<typeof createFeedbackSchema>;\nexport type CreateLinkDTO = z.output<typeof createLinkSchema>;\nexport type CreateVisitorDTO = z.output<typeof createVisitorSchema>;\nexport type UserProvidedDataDTO = z.output<typeof userProvidedDataSchema>;\nexport type UpdateVisitorDTO = z.output<typeof updateVisitorSchema>;\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["_null","_enum"],"sources":["../../src/schema/index.ts"],"sourcesContent":["import {\n enum as _enum,\n null as _null,\n array,\n boolean,\n e164,\n email,\n iso,\n maxLength,\n minLength,\n number,\n object,\n optional,\n pipe,\n record,\n regex,\n string,\n toLowerCase,\n toUpperCase,\n transform,\n trim,\n union,\n url,\n uuid,\n type z,\n} from 'zod/mini';\nimport type { Environment, Platform } from '../track/types';\n\nconst MAX_KEY_LENGTH = 128;\nconst MAX_VALUE_LENGTH = 512;\nconst MAX_PROPERTIES = 64;\n\n/**\n * Truncated rather than rejected. These schemas validate a whole batch at once, so refusing one\n * oversized value costs every event that traveled with it — and the values that overrun are the\n * ones derived from the page (a link's text, a URL carrying a long query), which no client can\n * bound in advance. A shortened value is worth more than a lost batch.\n */\nconst propertyText = pipe(\n string(),\n transform((value) => value.slice(0, MAX_VALUE_LENGTH))\n);\n\n/**\n * Keys are written by hand in instrumentation code, so an unusable one is a mistake in the host\n * rather than something the visitor typed. It is still dropped rather than rejected, for the same\n * reason: the mistake should cost that property, not the batch it happens to be in. Truncating a\n * key is not an option — two long keys would silently become one field.\n *\n * The key schema below is deliberately permissive so that this transform is reached at all; the\n * trimming it used to do happens here instead. `MAX_PROPERTIES` keeps the first N in insertion\n * order.\n */\nfunction takeProperties<T>(data: Record<string, T>): Record<string, T> {\n const result: Record<string, T> = {};\n let count = 0;\n for (const [rawKey, value] of Object.entries(data)) {\n if (count >= MAX_PROPERTIES) break;\n const key = rawKey.trim();\n if (!key || key.length > MAX_KEY_LENGTH) continue;\n result[key] = value;\n count++;\n }\n return result;\n}\n\n/**\n * Capped at GA4's own item-list limit, and truncated rather than rejected like every other\n * property limit here: an unbounded array is the one field a caller could still blow a batch\n * up with after the value and key limits.\n */\nconst MAX_ITEMS = 200;\n\nconst items = pipe(\n array(\n pipe(\n record(string(), union([propertyText, number(), boolean(), _null()])),\n transform(takeProperties)\n )\n ),\n transform((list) => list.slice(0, MAX_ITEMS))\n);\n\nexport const ALL_PLATFORMS = [\n 'ios',\n 'android',\n 'web',\n 'macos',\n 'windows',\n 'linux',\n 'unknown',\n] as const satisfies Platform[];\n\nexport const ALL_ENVIRONMENTS = ['development', 'production'] as const satisfies Environment[];\n\nexport const tagsSchema = object({\n os: optional(string()),\n os_name: optional(string()),\n os_version: optional(string()),\n browser: optional(string()),\n browser_name: optional(string()),\n browser_version: optional(string()),\n device: optional(string()),\n device_id: optional(string().check(trim(), minLength(1), maxLength(36))),\n device_type: optional(string()),\n device_vendor: optional(string()),\n device_pixel_ratio: optional(number()),\n screen_width: optional(number()),\n screen_height: optional(number()),\n screen_resolution: optional(\n pipe(\n string().check(regex(/^\\d+x\\d+$/)),\n transform((v) => v as `${number}x${number}`)\n )\n ),\n webdriver: optional(boolean()),\n release: optional(string()),\n language: optional(string()),\n time_zone: optional(string()),\n page_location: optional(string()),\n page_referrer: optional(string()),\n page_title: optional(string()),\n page_load_id: optional(string()),\n /**\n * @deprecated Renamed to `page_location` in 7.0.0. Accepted so that events from clients\n * still on an older SDK are not stripped of their page URL at this boundary — a browser\n * bundle stays cached long after a backend deploys. Remove once those clients are gone;\n * `pageLocation` in `server/page-location.ts` is the only reader.\n */\n source_url: optional(string()),\n // app info\n advertising_id: optional(string()),\n install_referrer: optional(string()),\n // Ad click ids (URL parameters) and ad platform cookies (underscore names); see AdvertisingInfo.\n // Meta Ads\n fbclid: optional(string()),\n ad_id: optional(string()),\n ad_name: optional(string()),\n adset_id: optional(string()),\n adset_name: optional(string()),\n campaign_id: optional(string()),\n campaign_name: optional(string()),\n placement: optional(string()),\n _fbc: optional(string()),\n _fbp: optional(string()),\n /**\n * @deprecated `fbc` / `fbp` / `rdt_uuid` were renamed to `_fbc` / `_fbp` / `_rdt_uuid` in 9.0.0.\n * Accepted so that conversions from clients still on an older SDK keep their match keys; the\n * senders read them only as a fallback (`server/click-ids.ts`). Remove once those clients are\n * gone.\n */\n fbc: optional(string()),\n fbp: optional(string()),\n rdt_uuid: optional(string()),\n // Google Ads\n gclid: optional(string()),\n gclsrc: optional(string()),\n gad_source: optional(string()),\n gad_campaignid: optional(string()),\n wbraid: optional(string()),\n gbraid: optional(string()),\n dclid: optional(string()),\n _gcl_aw: optional(string()),\n _gcl_gb: optional(string()),\n // Microsoft Ads\n msclkid: optional(string()),\n _uetmsclkid: optional(string()),\n // Reddit Ads\n rdt_cid: optional(string()),\n _rdt_cid: optional(string()),\n _rdt_uuid: optional(string()),\n // LinkedIn Ads\n li_fat_id: optional(string()),\n _li_fat_id: optional(string()),\n // OpenAI Ads\n oppref: optional(string()),\n __oppref: optional(string()),\n __obref: optional(string()),\n // other click ids\n ko_click_id: optional(string()),\n ScCid: optional(string()),\n ttclid: optional(string()),\n twclid: optional(string()),\n yclid: optional(string()),\n epik: optional(string()),\n // utm params\n utm_source: optional(string()),\n utm_medium: optional(string()),\n utm_campaign: optional(string()),\n utm_term: optional(string()),\n utm_content: optional(string()),\n utm_id: optional(string()),\n utm_source_platform: optional(string()),\n utm_creative_format: optional(string()),\n utm_marketing_tactic: optional(string()),\n});\n\nexport const propertiesSchema = optional(\n pipe(\n record(string(), union([propertyText, number(), boolean(), _null(), items])),\n transform(takeProperties)\n )\n);\n\n/**\n * How far an event's time may be from the server's before the client clock it was stamped with is\n * taken as wrong. A batch legitimately arrives late — a tab frozen in the background, a\n * session_start held back after a failed batch — by hours, not days; a phone set to another year\n * writes its sessions into that year.\n */\nconst MAX_CLOCK_SKEW = 24 * 60 * 60 * 1000;\n\n/**\n * Puts the events stamped by a wrong client clock onto the server's, where they are parsed. Only\n * the events outside `MAX_CLOCK_SKEW` move, so one bad event cannot drag the rest of its batch\n * along: they move together by their own latest one — the wrong clock at sending — keeping their\n * order and spacing, and one still out after that (a batch mixing two wrong clocks) is on no clock\n * at all and takes the server's time. Corrected rather than rejected, for the same reason values\n * are truncated: a wrong clock should cost the event its time, not the batch its events.\n */\nfunction alignClock<T extends { timestamp: string }>(events: T[], now = Date.now()): T[] {\n const within = (time: number) => Math.abs(now - time) <= MAX_CLOCK_SKEW;\n const times = events.map((event) => Date.parse(event.timestamp));\n const wrong = times.filter((time) => !within(time));\n if (wrong.length === 0) return events;\n const offset = now - Math.max(...wrong);\n return events.map((event, i) => {\n if (within(times[i])) return event;\n const shifted = times[i] + offset;\n return { ...event, timestamp: new Date(within(shifted) ? shifted : now).toISOString() };\n });\n}\n\nexport const createTrackEventSchema = pipe(\n array(\n object({\n name: string().check(trim(), minLength(1), maxLength(64)),\n visitor_id: uuid(),\n session_id: uuid(),\n platform: _enum(ALL_PLATFORMS),\n environment: _enum(ALL_ENVIRONMENTS),\n timestamp: iso.datetime(),\n tags: tagsSchema,\n properties: propertiesSchema,\n })\n ).check(minLength(1), maxLength(100)),\n transform((events) => alignClock(events))\n);\n\n/**\n * `POST /visitors`, what clients before 11.0 create their visitor with; 11.0 generates the id\n * itself and the server creates the visitor from its first events (README, \"Visitors\").\n * Kept for servers that still serve older clients.\n */\nexport const createVisitorSchema = object({\n device_id: string().check(trim(), minLength(1), maxLength(36)),\n platform: _enum(ALL_PLATFORMS),\n environment: _enum(ALL_ENVIRONMENTS),\n tags: tagsSchema,\n});\n\nconst emailValue = pipe(string().check(trim(), toLowerCase(), maxLength(320)), email());\n\n/** E.164: a plus sign (+) prefix, country code, then digits only, no dashes/parens/spaces. */\nconst phoneValue = pipe(string().check(trim()), e164());\n\nconst addressValue = object({\n first_name: optional(string().check(trim(), maxLength(128))),\n last_name: optional(string().check(trim(), maxLength(128))),\n street: optional(string().check(trim(), maxLength(256))),\n city: optional(string().check(trim(), maxLength(128))),\n /** User province, state, or region. Example: `Hampshire` */\n region: optional(string().check(trim(), maxLength(128))),\n postal_code: optional(string().check(trim(), maxLength(32))),\n /** 2-letter country code, per the ISO 3166-1 alpha-2 standard. Example: `UK` */\n country: optional(string().check(trim(), toUpperCase(), regex(/^[A-Z]{2}$/))),\n});\n\n/**\n * User-provided data (UPD) used for enhanced conversions, Customer Match, and demographics.\n * Values are sent unhashed; Google normalizes and hashes them before they reach its servers.\n *\n * Multiple values may be sent to increase the match rate: up to 3 emails, 3 phone numbers, and\n * 2 addresses.\n *\n * @see https://support.google.com/analytics/answer/14078702\n * @see https://support.google.com/google-ads/answer/13258081\n */\nexport const userProvidedDataSchema = object({\n email: optional(union([emailValue, array(emailValue).check(minLength(1), maxLength(3))])),\n phone_number: optional(union([phoneValue, array(phoneValue).check(minLength(1), maxLength(3))])),\n address: optional(union([addressValue, array(addressValue).check(minLength(1), maxLength(2))])),\n});\n\nexport const updateVisitorSchema = object({\n user_id: optional(uuid()),\n user_data: optional(userProvidedDataSchema),\n /**\n * Sent by clients before 11.1, which PATCHed their tags on every page load. From 11.1 the\n * server refreshes `visitor.tags` from each `session_start` — the moment the visit arrives —\n * and `setVisitor` sends none: at sign-in the page is no longer where the visit came in.\n */\n tags: optional(tagsSchema),\n});\n\nexport const createFeedbackSchema = object({\n name: string().check(minLength(1), maxLength(256)),\n email: email().check(maxLength(320)),\n message: string().check(minLength(1), maxLength(65536)),\n});\n\nconst noEmptyString = pipe(\n string().check(maxLength(256)),\n transform((v) => (v ? v : undefined))\n);\n\n/**\n * The schema for creating a link.\n * @see https://support.google.com/analytics/answer/10917952\n * */\nexport const createLinkSchema = object({\n /** The URL that the user is redirected to. */\n url: url().check(minLength(1), maxLength(1024)), // required\n\n /**\n * Campaign ID. Used to identify a specific campaign or promotion. This is a required key for GA4\n * data import. Use the same IDs that you use when uploading campaign cost data.\n */\n utm_id: optional(noEmptyString),\n\n /** Referrer, for example: google, newsletter4, billboard */\n utm_source: string().check(minLength(1), maxLength(256)), // required\n\n /** Marketing medium, for example: cpc, banner, email */\n utm_medium: string().check(minLength(1), maxLength(256)), // required\n\n /** Product, slogan, promo code, for example, spring_sale */\n utm_campaign: string().check(minLength(1), maxLength(256)), // required\n\n /** Paid keyword */\n utm_term: optional(noEmptyString),\n\n /**\n * Use to differentiate creatives. For example, if you have two call-to-action links within the\n * same email message, you can use utm_content and set different values for each so you can tell\n * which version is more effective.\n */\n utm_content: optional(noEmptyString),\n\n /**\n * The platform responsible for directing traffic to a given Analytics property (such as a buying\n * platform that sets budgets and targeting criteria or a platform that manages organic traffic\n * data). For example, Search Ads 360 or Display & Video 360.\n */\n utm_source_platform: optional(noEmptyString),\n\n /**\n * Type of creative, for example, display, native, video, search, utm_creative_format is not\n * currently reported in Google Analytics 4 properties.\n */\n utm_creative_format: optional(noEmptyString),\n\n /**\n * Targeting criteria applied to a campaign, for example, remarketing, prospecting,\n * utm_marketing_tactic is not currently reported in Google Analytics 4 properties.\n * */\n utm_marketing_tactic: optional(noEmptyString),\n});\n\nexport type CreateTrackEventDTO = z.output<typeof createTrackEventSchema>;\nexport type CreateFeedbackDTO = z.output<typeof createFeedbackSchema>;\nexport type CreateLinkDTO = z.output<typeof createLinkSchema>;\nexport type CreateVisitorDTO = z.output<typeof createVisitorSchema>;\nexport type UserProvidedDataDTO = z.output<typeof userProvidedDataSchema>;\nexport type UpdateVisitorDTO = z.output<typeof updateVisitorSchema>;\n"],"mappings":"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"}
@@ -7,14 +7,13 @@ function sendGAEvent(name, properties) {
7
7
  }
8
8
  window.gtag("event", name, properties);
9
9
  }
10
- function setGAUser({ user_id, user_data, properties }) {
10
+ function setGAUser({ user_id, user_data }) {
11
11
  if (typeof window === "undefined" || !window.gtag) {
12
12
  console.warn("GA has not been initialized");
13
13
  return;
14
14
  }
15
15
  if (user_id) window.gtag("set", "user_id", user_id);
16
16
  if (user_data) window.gtag("set", "user_data", user_data);
17
- if (properties) window.gtag("set", "user_properties", properties);
18
17
  }
19
18
  //#endregion
20
19
  exports.sendGAEvent = sendGAEvent;
@@ -1 +1 @@
1
- {"version":3,"file":"google-analytics.cjs","names":[],"sources":["../../src/third-parties/google-analytics.ts"],"sourcesContent":["import type { UpdateVisitorDTO } from '../schema/index';\nimport type { Gtag } from '../track/gtag';\nimport type { EventName, TrackName, TrackProperties } from '../track/types';\n\ndeclare global {\n interface Window {\n /** Undefined until the Google tag (gtag.js) script has loaded. */\n gtag?: Gtag['gtag'];\n }\n}\n\nexport function sendGAEvent<T extends EventName>(\n name: TrackName<T>,\n properties?: TrackProperties<T>\n) {\n if (typeof window === 'undefined' || !window.gtag) {\n console.warn('GA has not been initialized');\n return;\n }\n window.gtag('event', name, properties);\n}\n\nexport function setGAUser({ user_id, user_data, properties }: UpdateVisitorDTO) {\n if (typeof window === 'undefined' || !window.gtag) {\n console.warn('GA has not been initialized');\n return;\n }\n if (user_id) window.gtag('set', 'user_id', user_id);\n if (user_data) window.gtag('set', 'user_data', user_data);\n if (properties) window.gtag('set', 'user_properties', properties as never);\n}\n"],"mappings":";;AAWA,SAAgB,YACd,MACA,YACA;CACA,IAAI,OAAO,WAAW,eAAe,CAAC,OAAO,MAAM;EACjD,QAAQ,KAAK,6BAA6B;EAC1C;CACF;CACA,OAAO,KAAK,SAAS,MAAM,UAAU;AACvC;AAEA,SAAgB,UAAU,EAAE,SAAS,WAAW,cAAgC;CAC9E,IAAI,OAAO,WAAW,eAAe,CAAC,OAAO,MAAM;EACjD,QAAQ,KAAK,6BAA6B;EAC1C;CACF;CACA,IAAI,SAAS,OAAO,KAAK,OAAO,WAAW,OAAO;CAClD,IAAI,WAAW,OAAO,KAAK,OAAO,aAAa,SAAS;CACxD,IAAI,YAAY,OAAO,KAAK,OAAO,mBAAmB,UAAmB;AAC3E"}
1
+ {"version":3,"file":"google-analytics.cjs","names":[],"sources":["../../src/third-parties/google-analytics.ts"],"sourcesContent":["import type { UpdateVisitorDTO } from '../schema/index';\nimport type { Gtag } from '../track/gtag';\nimport type { EventName, TrackName, TrackProperties } from '../track/types';\n\ndeclare global {\n interface Window {\n /** Undefined until the Google tag (gtag.js) script has loaded. */\n gtag?: Gtag['gtag'];\n }\n}\n\nexport function sendGAEvent<T extends EventName>(\n name: TrackName<T>,\n properties?: TrackProperties<T>\n) {\n if (typeof window === 'undefined' || !window.gtag) {\n console.warn('GA has not been initialized');\n return;\n }\n window.gtag('event', name, properties);\n}\n\nexport function setGAUser({ user_id, user_data }: UpdateVisitorDTO) {\n if (typeof window === 'undefined' || !window.gtag) {\n console.warn('GA has not been initialized');\n return;\n }\n if (user_id) window.gtag('set', 'user_id', user_id);\n if (user_data) window.gtag('set', 'user_data', user_data);\n}\n"],"mappings":";;AAWA,SAAgB,YACd,MACA,YACA;CACA,IAAI,OAAO,WAAW,eAAe,CAAC,OAAO,MAAM;EACjD,QAAQ,KAAK,6BAA6B;EAC1C;CACF;CACA,OAAO,KAAK,SAAS,MAAM,UAAU;AACvC;AAEA,SAAgB,UAAU,EAAE,SAAS,aAA+B;CAClE,IAAI,OAAO,WAAW,eAAe,CAAC,OAAO,MAAM;EACjD,QAAQ,KAAK,6BAA6B;EAC1C;CACF;CACA,IAAI,SAAS,OAAO,KAAK,OAAO,WAAW,OAAO;CAClD,IAAI,WAAW,OAAO,KAAK,OAAO,aAAa,SAAS;AAC1D"}
@@ -9,6 +9,6 @@ declare global {
9
9
  }
10
10
  }
11
11
  export declare function sendGAEvent<T extends EventName>(name: TrackName<T>, properties?: TrackProperties<T>): void;
12
- export declare function setGAUser({ user_id, user_data, properties }: UpdateVisitorDTO): void;
12
+ export declare function setGAUser({ user_id, user_data }: UpdateVisitorDTO): void;
13
13
  //#endregion
14
14
  //# sourceMappingURL=google-analytics.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"google-analytics.d.cts","names":[],"sources":["../../src/third-parties/google-analytics.ts"],"mappings":";;;;QAIQ;YACI;;IAER,OAAO;;;wBAIK,YAAY,UAAU,WACpC,MAAM,UAAU,IAChB,aAAa,gBAAgB;wBASf,YAAY,SAAS,WAAW,cAAc"}
1
+ {"version":3,"file":"google-analytics.d.cts","names":[],"sources":["../../src/third-parties/google-analytics.ts"],"mappings":";;;;QAIQ;YACI;;IAER,OAAO;;;wBAIK,YAAY,UAAU,WACpC,MAAM,UAAU,IAChB,aAAa,gBAAgB;wBASf,YAAY,SAAS,aAAa"}
@@ -9,6 +9,6 @@ declare global {
9
9
  }
10
10
  }
11
11
  export declare function sendGAEvent<T extends EventName>(name: TrackName<T>, properties?: TrackProperties<T>): void;
12
- export declare function setGAUser({ user_id, user_data, properties }: UpdateVisitorDTO): void;
12
+ export declare function setGAUser({ user_id, user_data }: UpdateVisitorDTO): void;
13
13
  //#endregion
14
14
  //# sourceMappingURL=google-analytics.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"google-analytics.d.mts","names":[],"sources":["../../src/third-parties/google-analytics.ts"],"mappings":";;;;QAIQ;YACI;;IAER,OAAO;;;wBAIK,YAAY,UAAU,WACpC,MAAM,UAAU,IAChB,aAAa,gBAAgB;wBASf,YAAY,SAAS,WAAW,cAAc"}
1
+ {"version":3,"file":"google-analytics.d.mts","names":[],"sources":["../../src/third-parties/google-analytics.ts"],"mappings":";;;;QAIQ;YACI;;IAER,OAAO;;;wBAIK,YAAY,UAAU,WACpC,MAAM,UAAU,IAChB,aAAa,gBAAgB;wBASf,YAAY,SAAS,aAAa"}
@@ -6,14 +6,13 @@ function sendGAEvent(name, properties) {
6
6
  }
7
7
  window.gtag("event", name, properties);
8
8
  }
9
- function setGAUser({ user_id, user_data, properties }) {
9
+ function setGAUser({ user_id, user_data }) {
10
10
  if (typeof window === "undefined" || !window.gtag) {
11
11
  console.warn("GA has not been initialized");
12
12
  return;
13
13
  }
14
14
  if (user_id) window.gtag("set", "user_id", user_id);
15
15
  if (user_data) window.gtag("set", "user_data", user_data);
16
- if (properties) window.gtag("set", "user_properties", properties);
17
16
  }
18
17
  //#endregion
19
18
  export { sendGAEvent, setGAUser };
@@ -1 +1 @@
1
- {"version":3,"file":"google-analytics.mjs","names":[],"sources":["../../src/third-parties/google-analytics.ts"],"sourcesContent":["import type { UpdateVisitorDTO } from '../schema/index';\nimport type { Gtag } from '../track/gtag';\nimport type { EventName, TrackName, TrackProperties } from '../track/types';\n\ndeclare global {\n interface Window {\n /** Undefined until the Google tag (gtag.js) script has loaded. */\n gtag?: Gtag['gtag'];\n }\n}\n\nexport function sendGAEvent<T extends EventName>(\n name: TrackName<T>,\n properties?: TrackProperties<T>\n) {\n if (typeof window === 'undefined' || !window.gtag) {\n console.warn('GA has not been initialized');\n return;\n }\n window.gtag('event', name, properties);\n}\n\nexport function setGAUser({ user_id, user_data, properties }: UpdateVisitorDTO) {\n if (typeof window === 'undefined' || !window.gtag) {\n console.warn('GA has not been initialized');\n return;\n }\n if (user_id) window.gtag('set', 'user_id', user_id);\n if (user_data) window.gtag('set', 'user_data', user_data);\n if (properties) window.gtag('set', 'user_properties', properties as never);\n}\n"],"mappings":";AAWA,SAAgB,YACd,MACA,YACA;CACA,IAAI,OAAO,WAAW,eAAe,CAAC,OAAO,MAAM;EACjD,QAAQ,KAAK,6BAA6B;EAC1C;CACF;CACA,OAAO,KAAK,SAAS,MAAM,UAAU;AACvC;AAEA,SAAgB,UAAU,EAAE,SAAS,WAAW,cAAgC;CAC9E,IAAI,OAAO,WAAW,eAAe,CAAC,OAAO,MAAM;EACjD,QAAQ,KAAK,6BAA6B;EAC1C;CACF;CACA,IAAI,SAAS,OAAO,KAAK,OAAO,WAAW,OAAO;CAClD,IAAI,WAAW,OAAO,KAAK,OAAO,aAAa,SAAS;CACxD,IAAI,YAAY,OAAO,KAAK,OAAO,mBAAmB,UAAmB;AAC3E"}
1
+ {"version":3,"file":"google-analytics.mjs","names":[],"sources":["../../src/third-parties/google-analytics.ts"],"sourcesContent":["import type { UpdateVisitorDTO } from '../schema/index';\nimport type { Gtag } from '../track/gtag';\nimport type { EventName, TrackName, TrackProperties } from '../track/types';\n\ndeclare global {\n interface Window {\n /** Undefined until the Google tag (gtag.js) script has loaded. */\n gtag?: Gtag['gtag'];\n }\n}\n\nexport function sendGAEvent<T extends EventName>(\n name: TrackName<T>,\n properties?: TrackProperties<T>\n) {\n if (typeof window === 'undefined' || !window.gtag) {\n console.warn('GA has not been initialized');\n return;\n }\n window.gtag('event', name, properties);\n}\n\nexport function setGAUser({ user_id, user_data }: UpdateVisitorDTO) {\n if (typeof window === 'undefined' || !window.gtag) {\n console.warn('GA has not been initialized');\n return;\n }\n if (user_id) window.gtag('set', 'user_id', user_id);\n if (user_data) window.gtag('set', 'user_data', user_data);\n}\n"],"mappings":";AAWA,SAAgB,YACd,MACA,YACA;CACA,IAAI,OAAO,WAAW,eAAe,CAAC,OAAO,MAAM;EACjD,QAAQ,KAAK,6BAA6B;EAC1C;CACF;CACA,OAAO,KAAK,SAAS,MAAM,UAAU;AACvC;AAEA,SAAgB,UAAU,EAAE,SAAS,aAA+B;CAClE,IAAI,OAAO,WAAW,eAAe,CAAC,OAAO,MAAM;EACjD,QAAQ,KAAK,6BAA6B;EAC1C;CACF;CACA,IAAI,SAAS,OAAO,KAAK,OAAO,WAAW,OAAO;CAClD,IAAI,WAAW,OAAO,KAAK,OAAO,aAAa,SAAS;AAC1D"}
@@ -22,20 +22,16 @@ function visitorId() {
22
22
  }
23
23
  async function setVisitor(dto) {
24
24
  const id = visitorId();
25
- const body = {
26
- ...dto,
27
- tags: await require_setup_index.config.getTags()
28
- };
29
25
  const response = await (0, _shware_utils.fetch)(`${require_setup_index.config.endpoint}/visitors/${id}`, {
30
26
  method: "PATCH",
31
27
  credentials: "include",
32
28
  headers: await require_setup_index.config.getHeaders(),
33
- body: JSON.stringify(body)
29
+ body: JSON.stringify(dto)
34
30
  });
35
31
  if (!response.ok) throw new Error("Failed to set visitor");
36
32
  const data = await response.json();
37
33
  const identity = {
38
- ...body,
34
+ ...dto,
39
35
  distinct_id: data.distinct_id ?? null
40
36
  };
41
37
  require_setup_index.config.thirdPartyUserSetters.forEach((setter) => {
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["config","keys","uuidv7","fetch"],"sources":["../../src/visitor/index.ts"],"sourcesContent":["import { fetch } from '@shware/utils';\nimport { v7 as uuidv7 } from 'uuid';\nimport { keys } from '../constants/storage';\nimport type { UpdateVisitorDTO } from '../schema/index';\nimport { config } from '../setup/index';\nimport type { Visitor } from './types';\n\n/**\n * This visitor's id: generated here on the first visit (uuidv7) and kept in `config.storage`, so\n * it exists the moment the page loads. The first events, and the beacon of a visit left within a\n * second, go out without waiting for a round trip; the server creates the visitor from its first\n * events. An id a server issued to an older client is kept as it is: the visitor continues.\n *\n * Needs a server that creates visitors from events (see the README, \"Visitors\"); one that still\n * only creates them on `POST /visitors` rejects the events of a new visitor.\n */\nexport function visitorId(): string {\n const stored = config.storage.getItem(keys.visitor_id);\n if (stored && stored !== 'undefined') return stored;\n const id = uuidv7();\n config.storage.setItem(keys.visitor_id, id);\n return id;\n}\n\nexport async function setVisitor(dto: Omit<UpdateVisitorDTO, 'tags'>) {\n const id = visitorId();\n const body: UpdateVisitorDTO = { ...dto, tags: await config.getTags() };\n const response = await fetch(`${config.endpoint}/visitors/${id}`, {\n method: 'PATCH',\n credentials: 'include',\n headers: await config.getHeaders(),\n body: JSON.stringify(body),\n });\n\n if (!response.ok) throw new Error('Failed to set visitor');\n const data = (await response.json()) as Visitor;\n\n // Setters get the server's distinct_id — the person the visitor now belongs to — not anything\n // the client could have said about it.\n const identity = { ...body, distinct_id: data.distinct_id ?? null };\n config.thirdPartyUserSetters.forEach((setter) => {\n try {\n setter(identity);\n } catch (e: unknown) {\n // The visitor was updated before this ran, so a third-party setter throwing must not reject\n // a call that already succeeded.\n if (e instanceof Error) console.log(e.message);\n }\n });\n return data;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAgBA,SAAgB,YAAoB;CAClC,MAAM,SAASA,oBAAAA,OAAO,QAAQ,QAAQC,0BAAAA,KAAK,UAAU;CACrD,IAAI,UAAU,WAAW,aAAa,OAAO;CAC7C,MAAM,MAAA,GAAKC,KAAAA,GAAAA,CAAO;CAClB,oBAAA,OAAO,QAAQ,QAAQD,0BAAAA,KAAK,YAAY,EAAE;CAC1C,OAAO;AACT;AAEA,eAAsB,WAAW,KAAqC;CACpE,MAAM,KAAK,UAAU;CACrB,MAAM,OAAyB;EAAE,GAAG;EAAK,MAAM,MAAMD,oBAAAA,OAAO,QAAQ;CAAE;CACtE,MAAM,WAAW,OAAA,GAAMG,cAAAA,MAAAA,CAAM,GAAGH,oBAAAA,OAAO,SAAS,YAAY,MAAM;EAChE,QAAQ;EACR,aAAa;EACb,SAAS,MAAMA,oBAAAA,OAAO,WAAW;EACjC,MAAM,KAAK,UAAU,IAAI;CAC3B,CAAC;CAED,IAAI,CAAC,SAAS,IAAI,MAAM,IAAI,MAAM,uBAAuB;CACzD,MAAM,OAAQ,MAAM,SAAS,KAAK;CAIlC,MAAM,WAAW;EAAE,GAAG;EAAM,aAAa,KAAK,eAAe;CAAK;CAClE,oBAAA,OAAO,sBAAsB,SAAS,WAAW;EAC/C,IAAI;GACF,OAAO,QAAQ;EACjB,SAAS,GAAY;GAGnB,IAAI,aAAa,OAAO,QAAQ,IAAI,EAAE,OAAO;EAC/C;CACF,CAAC;CACD,OAAO;AACT"}
1
+ {"version":3,"file":"index.cjs","names":["config","keys","uuidv7","fetch"],"sources":["../../src/visitor/index.ts"],"sourcesContent":["import { fetch } from '@shware/utils';\nimport { v7 as uuidv7 } from 'uuid';\nimport { keys } from '../constants/storage';\nimport type { UpdateVisitorDTO } from '../schema/index';\nimport { config } from '../setup/index';\nimport type { Visitor } from './types';\n\n/**\n * This visitor's id: generated here on the first visit (uuidv7) and kept in `config.storage`, so\n * it exists the moment the page loads. The first events, and the beacon of a visit left within a\n * second, go out without waiting for a round trip; the server creates the visitor from its first\n * events. An id a server issued to an older client is kept as it is: the visitor continues.\n *\n * Needs a server that creates visitors from events (see the README, \"Visitors\"); one that still\n * only creates them on `POST /visitors` rejects the events of a new visitor.\n */\nexport function visitorId(): string {\n const stored = config.storage.getItem(keys.visitor_id);\n if (stored && stored !== 'undefined') return stored;\n const id = uuidv7();\n config.storage.setItem(keys.visitor_id, id);\n return id;\n}\n\nexport async function setVisitor(dto: Omit<UpdateVisitorDTO, 'tags'>) {\n const id = visitorId();\n const response = await fetch(`${config.endpoint}/visitors/${id}`, {\n method: 'PATCH',\n credentials: 'include',\n headers: await config.getHeaders(),\n body: JSON.stringify(dto),\n });\n\n if (!response.ok) throw new Error('Failed to set visitor');\n const data = (await response.json()) as Visitor;\n\n // Setters get the server's distinct_id — the person the visitor now belongs to — not anything\n // the client could have said about it.\n const identity = { ...dto, distinct_id: data.distinct_id ?? null };\n config.thirdPartyUserSetters.forEach((setter) => {\n try {\n setter(identity);\n } catch (e: unknown) {\n // The visitor was updated before this ran, so a third-party setter throwing must not reject\n // a call that already succeeded.\n if (e instanceof Error) console.log(e.message);\n }\n });\n return data;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAgBA,SAAgB,YAAoB;CAClC,MAAM,SAASA,oBAAAA,OAAO,QAAQ,QAAQC,0BAAAA,KAAK,UAAU;CACrD,IAAI,UAAU,WAAW,aAAa,OAAO;CAC7C,MAAM,MAAA,GAAKC,KAAAA,GAAAA,CAAO;CAClB,oBAAA,OAAO,QAAQ,QAAQD,0BAAAA,KAAK,YAAY,EAAE;CAC1C,OAAO;AACT;AAEA,eAAsB,WAAW,KAAqC;CACpE,MAAM,KAAK,UAAU;CACrB,MAAM,WAAW,OAAA,GAAME,cAAAA,MAAAA,CAAM,GAAGH,oBAAAA,OAAO,SAAS,YAAY,MAAM;EAChE,QAAQ;EACR,aAAa;EACb,SAAS,MAAMA,oBAAAA,OAAO,WAAW;EACjC,MAAM,KAAK,UAAU,GAAG;CAC1B,CAAC;CAED,IAAI,CAAC,SAAS,IAAI,MAAM,IAAI,MAAM,uBAAuB;CACzD,MAAM,OAAQ,MAAM,SAAS,KAAK;CAIlC,MAAM,WAAW;EAAE,GAAG;EAAK,aAAa,KAAK,eAAe;CAAK;CACjE,oBAAA,OAAO,sBAAsB,SAAS,WAAW;EAC/C,IAAI;GACF,OAAO,QAAQ;EACjB,SAAS,GAAY;GAGnB,IAAI,aAAa,OAAO,QAAQ,IAAI,EAAE,OAAO;EAC/C;CACF,CAAC;CACD,OAAO;AACT"}
@@ -21,20 +21,16 @@ function visitorId() {
21
21
  }
22
22
  async function setVisitor(dto) {
23
23
  const id = visitorId();
24
- const body = {
25
- ...dto,
26
- tags: await config.getTags()
27
- };
28
24
  const response = await fetch(`${config.endpoint}/visitors/${id}`, {
29
25
  method: "PATCH",
30
26
  credentials: "include",
31
27
  headers: await config.getHeaders(),
32
- body: JSON.stringify(body)
28
+ body: JSON.stringify(dto)
33
29
  });
34
30
  if (!response.ok) throw new Error("Failed to set visitor");
35
31
  const data = await response.json();
36
32
  const identity = {
37
- ...body,
33
+ ...dto,
38
34
  distinct_id: data.distinct_id ?? null
39
35
  };
40
36
  config.thirdPartyUserSetters.forEach((setter) => {
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["uuidv7"],"sources":["../../src/visitor/index.ts"],"sourcesContent":["import { fetch } from '@shware/utils';\nimport { v7 as uuidv7 } from 'uuid';\nimport { keys } from '../constants/storage';\nimport type { UpdateVisitorDTO } from '../schema/index';\nimport { config } from '../setup/index';\nimport type { Visitor } from './types';\n\n/**\n * This visitor's id: generated here on the first visit (uuidv7) and kept in `config.storage`, so\n * it exists the moment the page loads. The first events, and the beacon of a visit left within a\n * second, go out without waiting for a round trip; the server creates the visitor from its first\n * events. An id a server issued to an older client is kept as it is: the visitor continues.\n *\n * Needs a server that creates visitors from events (see the README, \"Visitors\"); one that still\n * only creates them on `POST /visitors` rejects the events of a new visitor.\n */\nexport function visitorId(): string {\n const stored = config.storage.getItem(keys.visitor_id);\n if (stored && stored !== 'undefined') return stored;\n const id = uuidv7();\n config.storage.setItem(keys.visitor_id, id);\n return id;\n}\n\nexport async function setVisitor(dto: Omit<UpdateVisitorDTO, 'tags'>) {\n const id = visitorId();\n const body: UpdateVisitorDTO = { ...dto, tags: await config.getTags() };\n const response = await fetch(`${config.endpoint}/visitors/${id}`, {\n method: 'PATCH',\n credentials: 'include',\n headers: await config.getHeaders(),\n body: JSON.stringify(body),\n });\n\n if (!response.ok) throw new Error('Failed to set visitor');\n const data = (await response.json()) as Visitor;\n\n // Setters get the server's distinct_id — the person the visitor now belongs to — not anything\n // the client could have said about it.\n const identity = { ...body, distinct_id: data.distinct_id ?? null };\n config.thirdPartyUserSetters.forEach((setter) => {\n try {\n setter(identity);\n } catch (e: unknown) {\n // The visitor was updated before this ran, so a third-party setter throwing must not reject\n // a call that already succeeded.\n if (e instanceof Error) console.log(e.message);\n }\n });\n return data;\n}\n"],"mappings":";;;;;;;;;;;;;;AAgBA,SAAgB,YAAoB;CAClC,MAAM,SAAS,OAAO,QAAQ,QAAQ,KAAK,UAAU;CACrD,IAAI,UAAU,WAAW,aAAa,OAAO;CAC7C,MAAM,KAAKA,GAAO;CAClB,OAAO,QAAQ,QAAQ,KAAK,YAAY,EAAE;CAC1C,OAAO;AACT;AAEA,eAAsB,WAAW,KAAqC;CACpE,MAAM,KAAK,UAAU;CACrB,MAAM,OAAyB;EAAE,GAAG;EAAK,MAAM,MAAM,OAAO,QAAQ;CAAE;CACtE,MAAM,WAAW,MAAM,MAAM,GAAG,OAAO,SAAS,YAAY,MAAM;EAChE,QAAQ;EACR,aAAa;EACb,SAAS,MAAM,OAAO,WAAW;EACjC,MAAM,KAAK,UAAU,IAAI;CAC3B,CAAC;CAED,IAAI,CAAC,SAAS,IAAI,MAAM,IAAI,MAAM,uBAAuB;CACzD,MAAM,OAAQ,MAAM,SAAS,KAAK;CAIlC,MAAM,WAAW;EAAE,GAAG;EAAM,aAAa,KAAK,eAAe;CAAK;CAClE,OAAO,sBAAsB,SAAS,WAAW;EAC/C,IAAI;GACF,OAAO,QAAQ;EACjB,SAAS,GAAY;GAGnB,IAAI,aAAa,OAAO,QAAQ,IAAI,EAAE,OAAO;EAC/C;CACF,CAAC;CACD,OAAO;AACT"}
1
+ {"version":3,"file":"index.mjs","names":["uuidv7"],"sources":["../../src/visitor/index.ts"],"sourcesContent":["import { fetch } from '@shware/utils';\nimport { v7 as uuidv7 } from 'uuid';\nimport { keys } from '../constants/storage';\nimport type { UpdateVisitorDTO } from '../schema/index';\nimport { config } from '../setup/index';\nimport type { Visitor } from './types';\n\n/**\n * This visitor's id: generated here on the first visit (uuidv7) and kept in `config.storage`, so\n * it exists the moment the page loads. The first events, and the beacon of a visit left within a\n * second, go out without waiting for a round trip; the server creates the visitor from its first\n * events. An id a server issued to an older client is kept as it is: the visitor continues.\n *\n * Needs a server that creates visitors from events (see the README, \"Visitors\"); one that still\n * only creates them on `POST /visitors` rejects the events of a new visitor.\n */\nexport function visitorId(): string {\n const stored = config.storage.getItem(keys.visitor_id);\n if (stored && stored !== 'undefined') return stored;\n const id = uuidv7();\n config.storage.setItem(keys.visitor_id, id);\n return id;\n}\n\nexport async function setVisitor(dto: Omit<UpdateVisitorDTO, 'tags'>) {\n const id = visitorId();\n const response = await fetch(`${config.endpoint}/visitors/${id}`, {\n method: 'PATCH',\n credentials: 'include',\n headers: await config.getHeaders(),\n body: JSON.stringify(dto),\n });\n\n if (!response.ok) throw new Error('Failed to set visitor');\n const data = (await response.json()) as Visitor;\n\n // Setters get the server's distinct_id — the person the visitor now belongs to — not anything\n // the client could have said about it.\n const identity = { ...dto, distinct_id: data.distinct_id ?? null };\n config.thirdPartyUserSetters.forEach((setter) => {\n try {\n setter(identity);\n } catch (e: unknown) {\n // The visitor was updated before this ran, so a third-party setter throwing must not reject\n // a call that already succeeded.\n if (e instanceof Error) console.log(e.message);\n }\n });\n return data;\n}\n"],"mappings":";;;;;;;;;;;;;;AAgBA,SAAgB,YAAoB;CAClC,MAAM,SAAS,OAAO,QAAQ,QAAQ,KAAK,UAAU;CACrD,IAAI,UAAU,WAAW,aAAa,OAAO;CAC7C,MAAM,KAAKA,GAAO;CAClB,OAAO,QAAQ,QAAQ,KAAK,YAAY,EAAE;CAC1C,OAAO;AACT;AAEA,eAAsB,WAAW,KAAqC;CACpE,MAAM,KAAK,UAAU;CACrB,MAAM,WAAW,MAAM,MAAM,GAAG,OAAO,SAAS,YAAY,MAAM;EAChE,QAAQ;EACR,aAAa;EACb,SAAS,MAAM,OAAO,WAAW;EACjC,MAAM,KAAK,UAAU,GAAG;CAC1B,CAAC;CAED,IAAI,CAAC,SAAS,IAAI,MAAM,IAAI,MAAM,uBAAuB;CACzD,MAAM,OAAQ,MAAM,SAAS,KAAK;CAIlC,MAAM,WAAW;EAAE,GAAG;EAAK,aAAa,KAAK,eAAe;CAAK;CACjE,OAAO,sBAAsB,SAAS,WAAW;EAC/C,IAAI;GACF,OAAO,QAAQ;EACjB,SAAS,GAAY;GAGnB,IAAI,aAAa,OAAO,QAAQ,IAAI,EAAE,OAAO;EAC/C;CACF,CAAC;CACD,OAAO;AACT"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shware/analytics",
3
- "version": "11.0.1",
3
+ "version": "11.1.0",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",