@shware/analytics 8.8.0 → 8.10.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 +34 -0
- package/dist/attribution/index.cjs +274 -0
- package/dist/attribution/index.cjs.map +1 -0
- package/dist/attribution/index.d.cts +103 -0
- package/dist/attribution/index.d.cts.map +1 -0
- package/dist/attribution/index.d.mts +103 -0
- package/dist/attribution/index.d.mts.map +1 -0
- package/dist/attribution/index.mjs +257 -0
- package/dist/attribution/index.mjs.map +1 -0
- package/dist/schema/index.cjs +0 -1
- package/dist/schema/index.cjs.map +1 -1
- package/dist/schema/index.d.cts +0 -1
- package/dist/schema/index.d.cts.map +1 -1
- package/dist/schema/index.d.mts +0 -1
- package/dist/schema/index.d.mts.map +1 -1
- package/dist/schema/index.mjs +0 -1
- package/dist/schema/index.mjs.map +1 -1
- package/dist/third-parties/posthog.cjs +7 -1
- package/dist/third-parties/posthog.cjs.map +1 -1
- package/dist/third-parties/posthog.d.cts +8 -2
- package/dist/third-parties/posthog.d.cts.map +1 -1
- package/dist/third-parties/posthog.d.mts +8 -2
- package/dist/third-parties/posthog.d.mts.map +1 -1
- package/dist/third-parties/posthog.mjs +7 -1
- package/dist/third-parties/posthog.mjs.map +1 -1
- package/dist/visitor/index.cjs +5 -1
- package/dist/visitor/index.cjs.map +1 -1
- package/dist/visitor/index.mjs +5 -1
- package/dist/visitor/index.mjs.map +1 -1
- package/dist/visitor/types.d.cts +14 -2
- package/dist/visitor/types.d.cts.map +1 -1
- package/dist/visitor/types.d.mts +14 -2
- package/dist/visitor/types.d.mts.map +1 -1
- package/package.json +11 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"posthog.mjs","names":[],"sources":["../../src/third-parties/posthog.ts"],"sourcesContent":["import { posthog } from 'posthog-js';\nimport type {
|
|
1
|
+
{"version":3,"file":"posthog.mjs","names":[],"sources":["../../src/third-parties/posthog.ts"],"sourcesContent":["import { posthog } from 'posthog-js';\nimport type { EventName, TrackName, TrackProperties } from '../track/types';\nimport { getFirst } from '../utils/field';\nimport type { VisitorIdentity } from '../visitor/types';\n\nconst metrics = ['CLS', 'FCP', 'FID', 'INP', 'LCP', 'TTFB'];\n\nexport function sendPosthogEvent<T extends EventName>(\n name: TrackName<T>,\n properties?: TrackProperties<T>\n) {\n // `document`, not `window`: React Native defines `window` as an alias of `global`, so a\n // window check would pass there and then throw on `window.location`, which it has no such\n // alias for. `posthog-js` is the browser SDK and cannot run there anyway.\n if (typeof document === 'undefined') return;\n if (metrics.includes(name)) return;\n if (window.location.host.includes('127.0.0.1')) return;\n if (window.location.host.includes('localhost')) return;\n\n posthog.capture(name, properties);\n if (name === 'logout') {\n posthog.reset();\n }\n}\n\n/**\n * Identify the visitor to PostHog as the person the server says it is — `distinct_id`, the user's\n * id once someone has signed in. Only then: identifying an anonymous visitor by its own id would\n * make PostHog treat it as an identified person, and PostHog does not merge one identified person\n * into another when the user later signs in, so the pre-sign-in events would stay split off.\n */\nexport function setPosthogUser({ user_id, distinct_id, user_data }: VisitorIdentity) {\n if (!user_id) return;\n posthog.identify(distinct_id ?? user_id, { email: getFirst(user_data?.email) });\n}\n"],"mappings":";;;AAKA,MAAM,UAAU;CAAC;CAAO;CAAO;CAAO;CAAO;CAAO;AAAM;AAE1D,SAAgB,iBACd,MACA,YACA;CAIA,IAAI,OAAO,aAAa,aAAa;CACrC,IAAI,QAAQ,SAAS,IAAI,GAAG;CAC5B,IAAI,OAAO,SAAS,KAAK,SAAS,WAAW,GAAG;CAChD,IAAI,OAAO,SAAS,KAAK,SAAS,WAAW,GAAG;CAEhD,QAAQ,QAAQ,MAAM,UAAU;CAChC,IAAI,SAAS,UACX,QAAQ,MAAM;AAElB;;;;;;;AAQA,SAAgB,eAAe,EAAE,SAAS,aAAa,aAA8B;CACnF,IAAI,CAAC,SAAS;CACd,QAAQ,SAAS,eAAe,SAAS,EAAE,OAAO,SAAS,WAAW,KAAK,EAAE,CAAC;AAChF"}
|
package/dist/visitor/index.cjs
CHANGED
|
@@ -66,9 +66,13 @@ async function setVisitor(dto) {
|
|
|
66
66
|
});
|
|
67
67
|
if (!response.ok) throw new Error("Failed to set visitor");
|
|
68
68
|
const data = await response.json();
|
|
69
|
+
const identity = {
|
|
70
|
+
...body,
|
|
71
|
+
distinct_id: data.distinct_id ?? null
|
|
72
|
+
};
|
|
69
73
|
require_setup_index.config.thirdPartyUserSetters.forEach((setter) => {
|
|
70
74
|
try {
|
|
71
|
-
setter(
|
|
75
|
+
setter(identity);
|
|
72
76
|
} catch (e) {
|
|
73
77
|
if (e instanceof Error) console.log(e.message);
|
|
74
78
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["config","fetch","keys","cache"],"sources":["../../src/visitor/index.ts"],"sourcesContent":["import { fetch } from '@shware/utils';\nimport { keys } from '../constants/storage';\nimport type { CreateVisitorDTO, UpdateVisitorDTO } from '../schema/index';\nimport { cache, config } from '../setup/index';\nimport type { Visitor, VisitorProperties } from './types';\n\nasync function createVisitor(): Promise<Visitor> {\n const tags = await config.getTags();\n const dto: CreateVisitorDTO = {\n device_id: await config.getDeviceId(),\n platform: config.platform,\n environment: config.environment,\n tags,\n properties: tags as VisitorProperties,\n };\n\n const response = await fetch(`${config.endpoint}/visitors`, {\n method: 'POST',\n credentials: 'include',\n headers: await config.getHeaders(),\n body: JSON.stringify(dto),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to create visitor: ${response.status} ${await response.text()}`);\n }\n const data = (await response.json()) as Visitor;\n if (data.id) {\n config.storage.setItem(keys.visitor_id, data.id);\n }\n return data;\n}\n\nasync function getOrCreateVisitor(): Promise<Visitor> {\n const visitorId = config.storage.getItem(keys.visitor_id);\n if (visitorId && visitorId !== 'undefined') {\n // PATCH, not GET: `tags` is the last-touch counterpart to `initial_tags`,\n // and the only thing that ever refreshed it was `setVisitor`, which hosts\n // call when they identify a user. A visitor who never signs in therefore\n // kept the browser, screen, and release captured on their first ever page\n // load — for the rest of their life — leaving `tags` permanently equal to\n // `initial_tags` and the two columns pointless.\n //\n // Costs nothing extra: this replaces the request that was already here.\n const tags = await config.getTags();\n const response = await fetch(`${config.endpoint}/visitors/${visitorId}`, {\n method: 'PATCH',\n credentials: 'include',\n headers: await config.getHeaders(),\n body: JSON.stringify({ tags } satisfies UpdateVisitorDTO),\n });\n\n if (!response.ok) return createVisitor();\n const data = (await response.json()) as Visitor;\n\n if (data.id) {\n config.storage.setItem(keys.visitor_id, data.id);\n }\n return data;\n } else {\n return createVisitor();\n }\n}\n\nlet visitorFetcher: Promise<Visitor> | null = null;\n\nexport async function getVisitor(): Promise<Visitor> {\n if (cache.visitor) return cache.visitor;\n if (visitorFetcher) return visitorFetcher;\n visitorFetcher = getOrCreateVisitor();\n try {\n cache.visitor = await visitorFetcher;\n return cache.visitor;\n } finally {\n // In a `finally`, so a rejected attempt is not left in `visitorFetcher` for every later\n // caller to await again: `sendEvents` needs a visitor for every batch, and one failed\n // request would otherwise stop the page from reporting anything until it is reloaded.\n visitorFetcher = null;\n }\n}\n\nexport async function setVisitor(dto: Omit<UpdateVisitorDTO, 'tags'>) {\n const { id } = await getVisitor();\n const tags = await config.getTags();\n const body: UpdateVisitorDTO = { ...dto, tags };\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 config.thirdPartyUserSetters.forEach((setter) => {\n try {\n setter(
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["config","fetch","keys","cache"],"sources":["../../src/visitor/index.ts"],"sourcesContent":["import { fetch } from '@shware/utils';\nimport { keys } from '../constants/storage';\nimport type { CreateVisitorDTO, UpdateVisitorDTO } from '../schema/index';\nimport { cache, config } from '../setup/index';\nimport type { Visitor, VisitorProperties } from './types';\n\nasync function createVisitor(): Promise<Visitor> {\n const tags = await config.getTags();\n const dto: CreateVisitorDTO = {\n device_id: await config.getDeviceId(),\n platform: config.platform,\n environment: config.environment,\n tags,\n properties: tags as VisitorProperties,\n };\n\n const response = await fetch(`${config.endpoint}/visitors`, {\n method: 'POST',\n credentials: 'include',\n headers: await config.getHeaders(),\n body: JSON.stringify(dto),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to create visitor: ${response.status} ${await response.text()}`);\n }\n const data = (await response.json()) as Visitor;\n if (data.id) {\n config.storage.setItem(keys.visitor_id, data.id);\n }\n return data;\n}\n\nasync function getOrCreateVisitor(): Promise<Visitor> {\n const visitorId = config.storage.getItem(keys.visitor_id);\n if (visitorId && visitorId !== 'undefined') {\n // PATCH, not GET: `tags` is the last-touch counterpart to `initial_tags`,\n // and the only thing that ever refreshed it was `setVisitor`, which hosts\n // call when they identify a user. A visitor who never signs in therefore\n // kept the browser, screen, and release captured on their first ever page\n // load — for the rest of their life — leaving `tags` permanently equal to\n // `initial_tags` and the two columns pointless.\n //\n // Costs nothing extra: this replaces the request that was already here.\n const tags = await config.getTags();\n const response = await fetch(`${config.endpoint}/visitors/${visitorId}`, {\n method: 'PATCH',\n credentials: 'include',\n headers: await config.getHeaders(),\n body: JSON.stringify({ tags } satisfies UpdateVisitorDTO),\n });\n\n if (!response.ok) return createVisitor();\n const data = (await response.json()) as Visitor;\n\n if (data.id) {\n config.storage.setItem(keys.visitor_id, data.id);\n }\n return data;\n } else {\n return createVisitor();\n }\n}\n\nlet visitorFetcher: Promise<Visitor> | null = null;\n\nexport async function getVisitor(): Promise<Visitor> {\n if (cache.visitor) return cache.visitor;\n if (visitorFetcher) return visitorFetcher;\n visitorFetcher = getOrCreateVisitor();\n try {\n cache.visitor = await visitorFetcher;\n return cache.visitor;\n } finally {\n // In a `finally`, so a rejected attempt is not left in `visitorFetcher` for every later\n // caller to await again: `sendEvents` needs a visitor for every batch, and one failed\n // request would otherwise stop the page from reporting anything until it is reloaded.\n visitorFetcher = null;\n }\n}\n\nexport async function setVisitor(dto: Omit<UpdateVisitorDTO, 'tags'>) {\n const { id } = await getVisitor();\n const tags = await config.getTags();\n const body: UpdateVisitorDTO = { ...dto, tags };\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 skip\n // the cache write below or reject a call that already succeeded.\n if (e instanceof Error) console.log(e.message);\n }\n });\n cache.visitor = data;\n return data;\n}\n"],"mappings":";;;;;AAMA,eAAe,gBAAkC;CAC/C,MAAM,OAAO,MAAMA,oBAAAA,OAAO,QAAQ;CAClC,MAAM,MAAwB;EAC5B,WAAW,MAAMA,oBAAAA,OAAO,YAAY;EACpC,UAAUA,oBAAAA,OAAO;EACjB,aAAaA,oBAAAA,OAAO;EACpB;EACA,YAAY;CACd;CAEA,MAAM,WAAW,OAAA,GAAMC,cAAAA,MAAAA,CAAM,GAAGD,oBAAAA,OAAO,SAAS,YAAY;EAC1D,QAAQ;EACR,aAAa;EACb,SAAS,MAAMA,oBAAAA,OAAO,WAAW;EACjC,MAAM,KAAK,UAAU,GAAG;CAC1B,CAAC;CAED,IAAI,CAAC,SAAS,IACZ,MAAM,IAAI,MAAM,6BAA6B,SAAS,OAAO,GAAG,MAAM,SAAS,KAAK,GAAG;CAEzF,MAAM,OAAQ,MAAM,SAAS,KAAK;CAClC,IAAI,KAAK,IACP,oBAAA,OAAO,QAAQ,QAAQE,0BAAAA,KAAK,YAAY,KAAK,EAAE;CAEjD,OAAO;AACT;AAEA,eAAe,qBAAuC;CACpD,MAAM,YAAYF,oBAAAA,OAAO,QAAQ,QAAQE,0BAAAA,KAAK,UAAU;CACxD,IAAI,aAAa,cAAc,aAAa;EAS1C,MAAM,OAAO,MAAMF,oBAAAA,OAAO,QAAQ;EAClC,MAAM,WAAW,OAAA,GAAMC,cAAAA,MAAAA,CAAM,GAAGD,oBAAAA,OAAO,SAAS,YAAY,aAAa;GACvE,QAAQ;GACR,aAAa;GACb,SAAS,MAAMA,oBAAAA,OAAO,WAAW;GACjC,MAAM,KAAK,UAAU,EAAE,KAAK,CAA4B;EAC1D,CAAC;EAED,IAAI,CAAC,SAAS,IAAI,OAAO,cAAc;EACvC,MAAM,OAAQ,MAAM,SAAS,KAAK;EAElC,IAAI,KAAK,IACP,oBAAA,OAAO,QAAQ,QAAQE,0BAAAA,KAAK,YAAY,KAAK,EAAE;EAEjD,OAAO;CACT,OACE,OAAO,cAAc;AAEzB;AAEA,IAAI,iBAA0C;AAE9C,eAAsB,aAA+B;CACnD,IAAIC,oBAAAA,MAAM,SAAS,OAAOA,oBAAAA,MAAM;CAChC,IAAI,gBAAgB,OAAO;CAC3B,iBAAiB,mBAAmB;CACpC,IAAI;EACF,oBAAA,MAAM,UAAU,MAAM;EACtB,OAAOA,oBAAAA,MAAM;CACf,UAAU;EAIR,iBAAiB;CACnB;AACF;AAEA,eAAsB,WAAW,KAAqC;CACpE,MAAM,EAAE,OAAO,MAAM,WAAW;CAChC,MAAM,OAAO,MAAMH,oBAAAA,OAAO,QAAQ;CAClC,MAAM,OAAyB;EAAE,GAAG;EAAK;CAAK;CAC9C,MAAM,WAAW,OAAA,GAAMC,cAAAA,MAAAA,CAAM,GAAGD,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,oBAAA,MAAM,UAAU;CAChB,OAAO;AACT"}
|
package/dist/visitor/index.mjs
CHANGED
|
@@ -65,9 +65,13 @@ async function setVisitor(dto) {
|
|
|
65
65
|
});
|
|
66
66
|
if (!response.ok) throw new Error("Failed to set visitor");
|
|
67
67
|
const data = await response.json();
|
|
68
|
+
const identity = {
|
|
69
|
+
...body,
|
|
70
|
+
distinct_id: data.distinct_id ?? null
|
|
71
|
+
};
|
|
68
72
|
config.thirdPartyUserSetters.forEach((setter) => {
|
|
69
73
|
try {
|
|
70
|
-
setter(
|
|
74
|
+
setter(identity);
|
|
71
75
|
} catch (e) {
|
|
72
76
|
if (e instanceof Error) console.log(e.message);
|
|
73
77
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/visitor/index.ts"],"sourcesContent":["import { fetch } from '@shware/utils';\nimport { keys } from '../constants/storage';\nimport type { CreateVisitorDTO, UpdateVisitorDTO } from '../schema/index';\nimport { cache, config } from '../setup/index';\nimport type { Visitor, VisitorProperties } from './types';\n\nasync function createVisitor(): Promise<Visitor> {\n const tags = await config.getTags();\n const dto: CreateVisitorDTO = {\n device_id: await config.getDeviceId(),\n platform: config.platform,\n environment: config.environment,\n tags,\n properties: tags as VisitorProperties,\n };\n\n const response = await fetch(`${config.endpoint}/visitors`, {\n method: 'POST',\n credentials: 'include',\n headers: await config.getHeaders(),\n body: JSON.stringify(dto),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to create visitor: ${response.status} ${await response.text()}`);\n }\n const data = (await response.json()) as Visitor;\n if (data.id) {\n config.storage.setItem(keys.visitor_id, data.id);\n }\n return data;\n}\n\nasync function getOrCreateVisitor(): Promise<Visitor> {\n const visitorId = config.storage.getItem(keys.visitor_id);\n if (visitorId && visitorId !== 'undefined') {\n // PATCH, not GET: `tags` is the last-touch counterpart to `initial_tags`,\n // and the only thing that ever refreshed it was `setVisitor`, which hosts\n // call when they identify a user. A visitor who never signs in therefore\n // kept the browser, screen, and release captured on their first ever page\n // load — for the rest of their life — leaving `tags` permanently equal to\n // `initial_tags` and the two columns pointless.\n //\n // Costs nothing extra: this replaces the request that was already here.\n const tags = await config.getTags();\n const response = await fetch(`${config.endpoint}/visitors/${visitorId}`, {\n method: 'PATCH',\n credentials: 'include',\n headers: await config.getHeaders(),\n body: JSON.stringify({ tags } satisfies UpdateVisitorDTO),\n });\n\n if (!response.ok) return createVisitor();\n const data = (await response.json()) as Visitor;\n\n if (data.id) {\n config.storage.setItem(keys.visitor_id, data.id);\n }\n return data;\n } else {\n return createVisitor();\n }\n}\n\nlet visitorFetcher: Promise<Visitor> | null = null;\n\nexport async function getVisitor(): Promise<Visitor> {\n if (cache.visitor) return cache.visitor;\n if (visitorFetcher) return visitorFetcher;\n visitorFetcher = getOrCreateVisitor();\n try {\n cache.visitor = await visitorFetcher;\n return cache.visitor;\n } finally {\n // In a `finally`, so a rejected attempt is not left in `visitorFetcher` for every later\n // caller to await again: `sendEvents` needs a visitor for every batch, and one failed\n // request would otherwise stop the page from reporting anything until it is reloaded.\n visitorFetcher = null;\n }\n}\n\nexport async function setVisitor(dto: Omit<UpdateVisitorDTO, 'tags'>) {\n const { id } = await getVisitor();\n const tags = await config.getTags();\n const body: UpdateVisitorDTO = { ...dto, tags };\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 config.thirdPartyUserSetters.forEach((setter) => {\n try {\n setter(
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/visitor/index.ts"],"sourcesContent":["import { fetch } from '@shware/utils';\nimport { keys } from '../constants/storage';\nimport type { CreateVisitorDTO, UpdateVisitorDTO } from '../schema/index';\nimport { cache, config } from '../setup/index';\nimport type { Visitor, VisitorProperties } from './types';\n\nasync function createVisitor(): Promise<Visitor> {\n const tags = await config.getTags();\n const dto: CreateVisitorDTO = {\n device_id: await config.getDeviceId(),\n platform: config.platform,\n environment: config.environment,\n tags,\n properties: tags as VisitorProperties,\n };\n\n const response = await fetch(`${config.endpoint}/visitors`, {\n method: 'POST',\n credentials: 'include',\n headers: await config.getHeaders(),\n body: JSON.stringify(dto),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to create visitor: ${response.status} ${await response.text()}`);\n }\n const data = (await response.json()) as Visitor;\n if (data.id) {\n config.storage.setItem(keys.visitor_id, data.id);\n }\n return data;\n}\n\nasync function getOrCreateVisitor(): Promise<Visitor> {\n const visitorId = config.storage.getItem(keys.visitor_id);\n if (visitorId && visitorId !== 'undefined') {\n // PATCH, not GET: `tags` is the last-touch counterpart to `initial_tags`,\n // and the only thing that ever refreshed it was `setVisitor`, which hosts\n // call when they identify a user. A visitor who never signs in therefore\n // kept the browser, screen, and release captured on their first ever page\n // load — for the rest of their life — leaving `tags` permanently equal to\n // `initial_tags` and the two columns pointless.\n //\n // Costs nothing extra: this replaces the request that was already here.\n const tags = await config.getTags();\n const response = await fetch(`${config.endpoint}/visitors/${visitorId}`, {\n method: 'PATCH',\n credentials: 'include',\n headers: await config.getHeaders(),\n body: JSON.stringify({ tags } satisfies UpdateVisitorDTO),\n });\n\n if (!response.ok) return createVisitor();\n const data = (await response.json()) as Visitor;\n\n if (data.id) {\n config.storage.setItem(keys.visitor_id, data.id);\n }\n return data;\n } else {\n return createVisitor();\n }\n}\n\nlet visitorFetcher: Promise<Visitor> | null = null;\n\nexport async function getVisitor(): Promise<Visitor> {\n if (cache.visitor) return cache.visitor;\n if (visitorFetcher) return visitorFetcher;\n visitorFetcher = getOrCreateVisitor();\n try {\n cache.visitor = await visitorFetcher;\n return cache.visitor;\n } finally {\n // In a `finally`, so a rejected attempt is not left in `visitorFetcher` for every later\n // caller to await again: `sendEvents` needs a visitor for every batch, and one failed\n // request would otherwise stop the page from reporting anything until it is reloaded.\n visitorFetcher = null;\n }\n}\n\nexport async function setVisitor(dto: Omit<UpdateVisitorDTO, 'tags'>) {\n const { id } = await getVisitor();\n const tags = await config.getTags();\n const body: UpdateVisitorDTO = { ...dto, tags };\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 skip\n // the cache write below or reject a call that already succeeded.\n if (e instanceof Error) console.log(e.message);\n }\n });\n cache.visitor = data;\n return data;\n}\n"],"mappings":";;;;AAMA,eAAe,gBAAkC;CAC/C,MAAM,OAAO,MAAM,OAAO,QAAQ;CAClC,MAAM,MAAwB;EAC5B,WAAW,MAAM,OAAO,YAAY;EACpC,UAAU,OAAO;EACjB,aAAa,OAAO;EACpB;EACA,YAAY;CACd;CAEA,MAAM,WAAW,MAAM,MAAM,GAAG,OAAO,SAAS,YAAY;EAC1D,QAAQ;EACR,aAAa;EACb,SAAS,MAAM,OAAO,WAAW;EACjC,MAAM,KAAK,UAAU,GAAG;CAC1B,CAAC;CAED,IAAI,CAAC,SAAS,IACZ,MAAM,IAAI,MAAM,6BAA6B,SAAS,OAAO,GAAG,MAAM,SAAS,KAAK,GAAG;CAEzF,MAAM,OAAQ,MAAM,SAAS,KAAK;CAClC,IAAI,KAAK,IACP,OAAO,QAAQ,QAAQ,KAAK,YAAY,KAAK,EAAE;CAEjD,OAAO;AACT;AAEA,eAAe,qBAAuC;CACpD,MAAM,YAAY,OAAO,QAAQ,QAAQ,KAAK,UAAU;CACxD,IAAI,aAAa,cAAc,aAAa;EAS1C,MAAM,OAAO,MAAM,OAAO,QAAQ;EAClC,MAAM,WAAW,MAAM,MAAM,GAAG,OAAO,SAAS,YAAY,aAAa;GACvE,QAAQ;GACR,aAAa;GACb,SAAS,MAAM,OAAO,WAAW;GACjC,MAAM,KAAK,UAAU,EAAE,KAAK,CAA4B;EAC1D,CAAC;EAED,IAAI,CAAC,SAAS,IAAI,OAAO,cAAc;EACvC,MAAM,OAAQ,MAAM,SAAS,KAAK;EAElC,IAAI,KAAK,IACP,OAAO,QAAQ,QAAQ,KAAK,YAAY,KAAK,EAAE;EAEjD,OAAO;CACT,OACE,OAAO,cAAc;AAEzB;AAEA,IAAI,iBAA0C;AAE9C,eAAsB,aAA+B;CACnD,IAAI,MAAM,SAAS,OAAO,MAAM;CAChC,IAAI,gBAAgB,OAAO;CAC3B,iBAAiB,mBAAmB;CACpC,IAAI;EACF,MAAM,UAAU,MAAM;EACtB,OAAO,MAAM;CACf,UAAU;EAIR,iBAAiB;CACnB;AACF;AAEA,eAAsB,WAAW,KAAqC;CACpE,MAAM,EAAE,OAAO,MAAM,WAAW;CAChC,MAAM,OAAO,MAAM,OAAO,QAAQ;CAClC,MAAM,OAAyB;EAAE,GAAG;EAAK;CAAK;CAC9C,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,MAAM,UAAU;CAChB,OAAO;AACT"}
|
package/dist/visitor/types.d.cts
CHANGED
|
@@ -4,12 +4,24 @@ import { Environment, Platform, TrackTags } from "../track/types.cjs";
|
|
|
4
4
|
type VisitorProperties = Record<Lowercase<string>, string | number | boolean | null>;
|
|
5
5
|
interface Visitor {
|
|
6
6
|
id: string;
|
|
7
|
+
/**
|
|
8
|
+
* The person this visitor belongs to, kept by the server: the visitor's own id until someone
|
|
9
|
+
* signs in on it, the user's id from then on. What first-party attribution counts people by,
|
|
10
|
+
* and what third parties are told to identify the visitor as. Null only from a server that
|
|
11
|
+
* predates it.
|
|
12
|
+
*/
|
|
13
|
+
distinct_id: string | null;
|
|
7
14
|
device_id: string;
|
|
8
15
|
platform: Platform;
|
|
9
16
|
environment: Environment;
|
|
10
17
|
tags: TrackTags;
|
|
11
18
|
}
|
|
12
|
-
|
|
19
|
+
/**
|
|
20
|
+
* What a third-party user setter is handed after `setVisitor`: the payload that was sent, plus
|
|
21
|
+
* the server's `distinct_id` for the visitor as it now stands.
|
|
22
|
+
*/
|
|
23
|
+
type VisitorIdentity = UpdateVisitorDTO & Pick<Visitor, 'distinct_id'>;
|
|
24
|
+
type ThirdPartyUserSetter = (identity: VisitorIdentity) => void;
|
|
13
25
|
//#endregion
|
|
14
|
-
export { ThirdPartyUserSetter, Visitor, VisitorProperties };
|
|
26
|
+
export { ThirdPartyUserSetter, Visitor, VisitorIdentity, VisitorProperties };
|
|
15
27
|
//# sourceMappingURL=types.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.cts","names":[],"sources":["../../src/visitor/types.ts"],"mappings":";;;KAGY,oBAAoB,OAAO;UAEtB;EACf;EACA;EACA,UAAU;EACV,aAAa;EACb,MAAM
|
|
1
|
+
{"version":3,"file":"types.d.cts","names":[],"sources":["../../src/visitor/types.ts"],"mappings":";;;KAGY,oBAAoB,OAAO;UAEtB;EACf;;;;;;;EAOA;EACA;EACA,UAAU;EACV,aAAa;EACb,MAAM;;;;;;KAOI,kBAAkB,mBAAmB,KAAK;KAE1C,wBAAwB,UAAU"}
|
package/dist/visitor/types.d.mts
CHANGED
|
@@ -4,12 +4,24 @@ import { Environment, Platform, TrackTags } from "../track/types.mjs";
|
|
|
4
4
|
type VisitorProperties = Record<Lowercase<string>, string | number | boolean | null>;
|
|
5
5
|
interface Visitor {
|
|
6
6
|
id: string;
|
|
7
|
+
/**
|
|
8
|
+
* The person this visitor belongs to, kept by the server: the visitor's own id until someone
|
|
9
|
+
* signs in on it, the user's id from then on. What first-party attribution counts people by,
|
|
10
|
+
* and what third parties are told to identify the visitor as. Null only from a server that
|
|
11
|
+
* predates it.
|
|
12
|
+
*/
|
|
13
|
+
distinct_id: string | null;
|
|
7
14
|
device_id: string;
|
|
8
15
|
platform: Platform;
|
|
9
16
|
environment: Environment;
|
|
10
17
|
tags: TrackTags;
|
|
11
18
|
}
|
|
12
|
-
|
|
19
|
+
/**
|
|
20
|
+
* What a third-party user setter is handed after `setVisitor`: the payload that was sent, plus
|
|
21
|
+
* the server's `distinct_id` for the visitor as it now stands.
|
|
22
|
+
*/
|
|
23
|
+
type VisitorIdentity = UpdateVisitorDTO & Pick<Visitor, 'distinct_id'>;
|
|
24
|
+
type ThirdPartyUserSetter = (identity: VisitorIdentity) => void;
|
|
13
25
|
//#endregion
|
|
14
|
-
export { ThirdPartyUserSetter, Visitor, VisitorProperties };
|
|
26
|
+
export { ThirdPartyUserSetter, Visitor, VisitorIdentity, VisitorProperties };
|
|
15
27
|
//# sourceMappingURL=types.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.mts","names":[],"sources":["../../src/visitor/types.ts"],"mappings":";;;KAGY,oBAAoB,OAAO;UAEtB;EACf;EACA;EACA,UAAU;EACV,aAAa;EACb,MAAM
|
|
1
|
+
{"version":3,"file":"types.d.mts","names":[],"sources":["../../src/visitor/types.ts"],"mappings":";;;KAGY,oBAAoB,OAAO;UAEtB;EACf;;;;;;;EAOA;EACA;EACA,UAAU;EACV,aAAa;EACb,MAAM;;;;;;KAOI,kBAAkB,mBAAmB,KAAK;KAE1C,wBAAwB,UAAU"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shware/analytics",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.10.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -21,6 +21,16 @@
|
|
|
21
21
|
"default": "./dist/index.cjs"
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
|
+
"./attribution": {
|
|
25
|
+
"import": {
|
|
26
|
+
"types": "./dist/attribution/index.d.mts",
|
|
27
|
+
"default": "./dist/attribution/index.mjs"
|
|
28
|
+
},
|
|
29
|
+
"require": {
|
|
30
|
+
"types": "./dist/attribution/index.d.cts",
|
|
31
|
+
"default": "./dist/attribution/index.cjs"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
24
34
|
"./native": {
|
|
25
35
|
"import": {
|
|
26
36
|
"types": "./dist/native/index.d.mts",
|