@atmosfer/impressions 0.1.5 → 0.1.7

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/dist/index.d.mts CHANGED
@@ -29,6 +29,9 @@ type Tracker = {
29
29
  };
30
30
  declare function createTracker(cfg: TrackerConfig): Tracker;
31
31
 
32
- declare function useImpressions(config: TrackerConfig): Tracker;
32
+ type UseImpressionsOptions = {
33
+ trackOnMount?: boolean;
34
+ };
35
+ declare function useImpressions(config: TrackerConfig, options?: UseImpressionsOptions): Tracker;
33
36
 
34
37
  export { type ImpressionEvent, type RestaurantId, type Tracker, type TrackerConfig, createTracker, useImpressions };
package/dist/index.d.ts CHANGED
@@ -29,6 +29,9 @@ type Tracker = {
29
29
  };
30
30
  declare function createTracker(cfg: TrackerConfig): Tracker;
31
31
 
32
- declare function useImpressions(config: TrackerConfig): Tracker;
32
+ type UseImpressionsOptions = {
33
+ trackOnMount?: boolean;
34
+ };
35
+ declare function useImpressions(config: TrackerConfig, options?: UseImpressionsOptions): Tracker;
33
36
 
34
37
  export { type ImpressionEvent, type RestaurantId, type Tracker, type TrackerConfig, createTracker, useImpressions };
package/dist/index.js CHANGED
@@ -89,14 +89,6 @@ function createTracker(cfg) {
89
89
  keepalive: true
90
90
  });
91
91
  }
92
- function beacon(ev) {
93
- var _a;
94
- try {
95
- const blob = new Blob([JSON.stringify(ev)], { type: "application/json" });
96
- (_a = navigator.sendBeacon) == null ? void 0 : _a.call(navigator, state.endpoint, blob);
97
- } catch {
98
- }
99
- }
100
92
  function build(eventType, detail) {
101
93
  return {
102
94
  schema_version: 1,
@@ -108,21 +100,6 @@ function createTracker(cfg) {
108
100
  event_detail: { ...baseDetail(anonId), ...detail ?? {} }
109
101
  };
110
102
  }
111
- window.addEventListener("pagehide", () => {
112
- if (state.disabled) return;
113
- beacon(build("page_view"));
114
- });
115
- const origPush = history.pushState;
116
- history.pushState = function(...args) {
117
- origPush.apply(history, args);
118
- void post(build("page_view"));
119
- };
120
- const origReplace = history.replaceState;
121
- history.replaceState = function(...args) {
122
- origReplace.apply(history, args);
123
- void post(build("page_view"));
124
- };
125
- window.addEventListener("popstate", () => void post(build("page_view")));
126
103
  return {
127
104
  page: async (detail) => post(build("page_view", detail)),
128
105
  track: async (eventType, detail) => post(build(eventType, detail)),
@@ -138,13 +115,33 @@ function createTracker(cfg) {
138
115
  }
139
116
  };
140
117
  }
141
- function useImpressions(config) {
118
+ function useImpressions(config, options = {}) {
142
119
  const tracker = react.useMemo(
143
120
  () => createTracker(config),
144
121
  [config.endpoint, config.restaurantId, config.tableNo]
145
122
  );
123
+ const didTrackMount = react.useRef(false);
146
124
  react.useEffect(() => {
147
- void tracker.page();
125
+ if (options.trackOnMount === false) return;
126
+ if (didTrackMount.current) return;
127
+ const sendPageView = () => {
128
+ if (didTrackMount.current) return;
129
+ didTrackMount.current = true;
130
+ void tracker.page();
131
+ };
132
+ if (document.visibilityState === "visible") {
133
+ sendPageView();
134
+ return;
135
+ }
136
+ const onVisibility = () => {
137
+ if (document.visibilityState !== "visible") return;
138
+ document.removeEventListener("visibilitychange", onVisibility);
139
+ sendPageView();
140
+ };
141
+ document.addEventListener("visibilitychange", onVisibility);
142
+ return () => {
143
+ document.removeEventListener("visibilitychange", onVisibility);
144
+ };
148
145
  }, []);
149
146
  return tracker;
150
147
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/tracker.ts","../src/hook.ts"],"names":["useMemo","useEffect"],"mappings":"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","file":"index.js","sourcesContent":["export type RestaurantId = string;\n\nexport type ImpressionEvent = {\n schema_version: 1;\n event_id: string;\n ts: string;\n\n restaurant_id: RestaurantId;\n table_no?: number | null;\n\n event_type: string;\n event_detail: Record<string, any>;\n};\n\nexport type TrackerConfig = {\n endpoint: string;\n restaurantId: RestaurantId;\n tableNo?: number;\n headers?: Record<string, string>;\n debug?: boolean;\n disable?: boolean;\n anonIdKey?: string;\n};\n\nfunction uuidv4(): string {\n return crypto.randomUUID();\n}\n\nfunction safeGetLS(key: string): string | null {\n try {\n return localStorage.getItem(key);\n } catch {\n return null;\n }\n}\nfunction safeSetLS(key: string, val: string) {\n try {\n localStorage.setItem(key, val);\n } catch {}\n}\n\nfunction getAnonId(key: string) {\n const existing = safeGetLS(key);\n if (existing) return existing;\n const id = uuidv4();\n safeSetLS(key, id);\n return id;\n}\n\nfunction parseUtm() {\n const p = new URLSearchParams(location.search);\n const source = p.get(\"utm_source\");\n const medium = p.get(\"utm_medium\");\n const campaign = p.get(\"utm_campaign\");\n if (!source && !medium && !campaign) return undefined;\n return { source, medium, campaign };\n}\n\nfunction deviceType(): \"mobile\" | \"tablet\" | \"desktop\" {\n const w = Math.min(screen.width, screen.height);\n if (w <= 480) return \"mobile\";\n if (w <= 1024) return \"tablet\";\n return \"desktop\";\n}\n\nfunction baseDetail(anonId: string) {\n return {\n path: location.pathname + location.search,\n referrer: document.referrer || undefined,\n utm: parseUtm(),\n anon_id: anonId,\n language: navigator.language,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n device: { type: deviceType() },\n screen: { w: window.innerWidth, h: window.innerHeight },\n page: { title: document.title },\n };\n}\n\nexport type Tracker = {\n page: (detail?: Record<string, any>) => Promise<void>;\n track: (eventType: string, detail?: Record<string, any>) => Promise<void>;\n setContext: (\n ctx: Partial<{ restaurantId: RestaurantId; tableNo: number }>\n ) => void;\n disable: () => void;\n enable: () => void;\n};\n\nexport function createTracker(cfg: TrackerConfig): Tracker {\n const isBrowser =\n typeof window !== \"undefined\" &&\n typeof document !== \"undefined\" &&\n typeof navigator !== \"undefined\" &&\n typeof location !== \"undefined\";\n\n if (!isBrowser) {\n return {\n page: async () => {},\n track: async () => {},\n setContext: () => {},\n disable: () => {},\n enable: () => {},\n };\n }\n\n const anonKey = cfg.anonIdKey ?? \"sa_anon_id\";\n const anonId = getAnonId(anonKey);\n\n const state = {\n endpoint: cfg.endpoint,\n restaurantId: cfg.restaurantId,\n tableNo: cfg.tableNo,\n headers: cfg.headers ?? {},\n disabled: !!cfg.disable,\n debug: !!cfg.debug,\n };\n\n async function post(ev: ImpressionEvent) {\n if (state.disabled) return;\n\n if (state.debug) console.log(\"[impr] sending\", ev);\n\n await fetch(state.endpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", ...state.headers },\n body: JSON.stringify(ev),\n keepalive: true,\n });\n }\n\n function beacon(ev: ImpressionEvent) {\n try {\n const blob = new Blob([JSON.stringify(ev)], { type: \"application/json\" });\n navigator.sendBeacon?.(state.endpoint, blob);\n } catch {}\n }\n\n function build(\n eventType: string,\n detail?: Record<string, any>\n ): ImpressionEvent {\n return {\n schema_version: 1,\n event_id: uuidv4(),\n ts: new Date().toISOString(),\n restaurant_id: state.restaurantId,\n table_no: state.tableNo ?? null,\n event_type: eventType,\n event_detail: { ...baseDetail(anonId), ...(detail ?? {}) },\n };\n }\n\n // Unload best-effort\n window.addEventListener(\"pagehide\", () => {\n if (state.disabled) return;\n beacon(build(\"page_view\"));\n });\n\n // SPA navigation tracking (framework-agnostic)\n const origPush = history.pushState;\n history.pushState = function (...args: any) {\n origPush.apply(history, args as any);\n void post(build(\"page_view\"));\n } as any;\n\n const origReplace = history.replaceState;\n history.replaceState = function (...args: any) {\n origReplace.apply(history, args as any);\n void post(build(\"page_view\"));\n } as any;\n\n window.addEventListener(\"popstate\", () => void post(build(\"page_view\")));\n\n return {\n page: async (detail) => post(build(\"page_view\", detail)),\n track: async (eventType, detail) => post(build(eventType, detail)),\n setContext: (ctx) => {\n if (ctx.restaurantId !== undefined) state.restaurantId = ctx.restaurantId;\n if (ctx.tableNo !== undefined) state.tableNo = ctx.tableNo;\n },\n disable: () => {\n state.disabled = true;\n },\n enable: () => {\n state.disabled = false;\n },\n };\n}\n","import { useEffect, useMemo } from \"react\";\nimport { createTracker } from \"./tracker\";\nimport type { TrackerConfig } from \"./tracker\";\n\nexport function useImpressions(config: TrackerConfig) {\n const tracker = useMemo(\n () => createTracker(config),\n [config.endpoint, config.restaurantId, config.tableNo]\n );\n\n useEffect(() => {\n void tracker.page();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return tracker;\n}\n"]}
1
+ {"version":3,"sources":["../src/tracker.ts","../src/hook.ts"],"names":["useMemo","useRef","useEffect"],"mappings":"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","file":"index.js","sourcesContent":["export type RestaurantId = string;\n\nexport type ImpressionEvent = {\n schema_version: 1;\n event_id: string;\n ts: string;\n\n restaurant_id: RestaurantId;\n table_no?: number | null;\n\n event_type: string;\n event_detail: Record<string, any>;\n};\n\nexport type TrackerConfig = {\n endpoint: string;\n restaurantId: RestaurantId;\n tableNo?: number;\n headers?: Record<string, string>;\n debug?: boolean;\n disable?: boolean;\n anonIdKey?: string;\n};\n\nfunction uuidv4(): string {\n return crypto.randomUUID();\n}\n\nfunction safeGetLS(key: string): string | null {\n try {\n return localStorage.getItem(key);\n } catch {\n return null;\n }\n}\nfunction safeSetLS(key: string, val: string) {\n try {\n localStorage.setItem(key, val);\n } catch {}\n}\n\nfunction getAnonId(key: string) {\n const existing = safeGetLS(key);\n if (existing) return existing;\n const id = uuidv4();\n safeSetLS(key, id);\n return id;\n}\n\nfunction parseUtm() {\n const p = new URLSearchParams(location.search);\n const source = p.get(\"utm_source\");\n const medium = p.get(\"utm_medium\");\n const campaign = p.get(\"utm_campaign\");\n if (!source && !medium && !campaign) return undefined;\n return { source, medium, campaign };\n}\n\nfunction deviceType(): \"mobile\" | \"tablet\" | \"desktop\" {\n const w = Math.min(screen.width, screen.height);\n if (w <= 480) return \"mobile\";\n if (w <= 1024) return \"tablet\";\n return \"desktop\";\n}\n\nfunction baseDetail(anonId: string) {\n return {\n path: location.pathname + location.search,\n referrer: document.referrer || undefined,\n utm: parseUtm(),\n anon_id: anonId,\n language: navigator.language,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n device: { type: deviceType() },\n screen: { w: window.innerWidth, h: window.innerHeight },\n page: { title: document.title },\n };\n}\n\nexport type Tracker = {\n page: (detail?: Record<string, any>) => Promise<void>;\n track: (eventType: string, detail?: Record<string, any>) => Promise<void>;\n setContext: (\n ctx: Partial<{ restaurantId: RestaurantId; tableNo: number }>\n ) => void;\n disable: () => void;\n enable: () => void;\n};\n\nexport function createTracker(cfg: TrackerConfig): Tracker {\n const isBrowser =\n typeof window !== \"undefined\" &&\n typeof document !== \"undefined\" &&\n typeof navigator !== \"undefined\" &&\n typeof location !== \"undefined\";\n\n if (!isBrowser) {\n return {\n page: async () => {},\n track: async () => {},\n setContext: () => {},\n disable: () => {},\n enable: () => {},\n };\n }\n\n const anonKey = cfg.anonIdKey ?? \"sa_anon_id\";\n const anonId = getAnonId(anonKey);\n\n const state = {\n endpoint: cfg.endpoint,\n restaurantId: cfg.restaurantId,\n tableNo: cfg.tableNo,\n headers: cfg.headers ?? {},\n disabled: !!cfg.disable,\n debug: !!cfg.debug,\n };\n\n async function post(ev: ImpressionEvent) {\n if (state.disabled) return;\n\n if (state.debug) console.log(\"[impr] sending\", ev);\n\n await fetch(state.endpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", ...state.headers },\n body: JSON.stringify(ev),\n keepalive: true,\n });\n }\n\n function build(\n eventType: string,\n detail?: Record<string, any>\n ): ImpressionEvent {\n return {\n schema_version: 1,\n event_id: uuidv4(),\n ts: new Date().toISOString(),\n restaurant_id: state.restaurantId,\n table_no: state.tableNo ?? null,\n event_type: eventType,\n event_detail: { ...baseDetail(anonId), ...(detail ?? {}) },\n };\n }\n\n return {\n page: async (detail) => post(build(\"page_view\", detail)),\n track: async (eventType, detail) => post(build(eventType, detail)),\n setContext: (ctx) => {\n if (ctx.restaurantId !== undefined) state.restaurantId = ctx.restaurantId;\n if (ctx.tableNo !== undefined) state.tableNo = ctx.tableNo;\n },\n disable: () => {\n state.disabled = true;\n },\n enable: () => {\n state.disabled = false;\n },\n };\n}\n","import { useEffect, useMemo, useRef } from \"react\";\nimport { createTracker } from \"./tracker\";\nimport type { TrackerConfig } from \"./tracker\";\n\nexport type UseImpressionsOptions = {\n trackOnMount?: boolean;\n};\n\nexport function useImpressions(\n config: TrackerConfig,\n options: UseImpressionsOptions = {}\n) {\n const tracker = useMemo(\n () => createTracker(config),\n [config.endpoint, config.restaurantId, config.tableNo]\n );\n const didTrackMount = useRef(false);\n\n useEffect(() => {\n if (options.trackOnMount === false) return;\n if (didTrackMount.current) return;\n\n const sendPageView = () => {\n if (didTrackMount.current) return;\n didTrackMount.current = true;\n void tracker.page();\n };\n\n if (document.visibilityState === \"visible\") {\n sendPageView();\n return;\n }\n\n const onVisibility = () => {\n if (document.visibilityState !== \"visible\") return;\n document.removeEventListener(\"visibilitychange\", onVisibility);\n sendPageView();\n };\n\n document.addEventListener(\"visibilitychange\", onVisibility);\n return () => {\n document.removeEventListener(\"visibilitychange\", onVisibility);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return tracker;\n}\n"]}
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { useMemo, useEffect } from 'react';
1
+ import { useMemo, useRef, useEffect } from 'react';
2
2
 
3
3
  // src/tracker.ts
4
4
  function uuidv4() {
@@ -87,14 +87,6 @@ function createTracker(cfg) {
87
87
  keepalive: true
88
88
  });
89
89
  }
90
- function beacon(ev) {
91
- var _a;
92
- try {
93
- const blob = new Blob([JSON.stringify(ev)], { type: "application/json" });
94
- (_a = navigator.sendBeacon) == null ? void 0 : _a.call(navigator, state.endpoint, blob);
95
- } catch {
96
- }
97
- }
98
90
  function build(eventType, detail) {
99
91
  return {
100
92
  schema_version: 1,
@@ -106,21 +98,6 @@ function createTracker(cfg) {
106
98
  event_detail: { ...baseDetail(anonId), ...detail ?? {} }
107
99
  };
108
100
  }
109
- window.addEventListener("pagehide", () => {
110
- if (state.disabled) return;
111
- beacon(build("page_view"));
112
- });
113
- const origPush = history.pushState;
114
- history.pushState = function(...args) {
115
- origPush.apply(history, args);
116
- void post(build("page_view"));
117
- };
118
- const origReplace = history.replaceState;
119
- history.replaceState = function(...args) {
120
- origReplace.apply(history, args);
121
- void post(build("page_view"));
122
- };
123
- window.addEventListener("popstate", () => void post(build("page_view")));
124
101
  return {
125
102
  page: async (detail) => post(build("page_view", detail)),
126
103
  track: async (eventType, detail) => post(build(eventType, detail)),
@@ -136,13 +113,33 @@ function createTracker(cfg) {
136
113
  }
137
114
  };
138
115
  }
139
- function useImpressions(config) {
116
+ function useImpressions(config, options = {}) {
140
117
  const tracker = useMemo(
141
118
  () => createTracker(config),
142
119
  [config.endpoint, config.restaurantId, config.tableNo]
143
120
  );
121
+ const didTrackMount = useRef(false);
144
122
  useEffect(() => {
145
- void tracker.page();
123
+ if (options.trackOnMount === false) return;
124
+ if (didTrackMount.current) return;
125
+ const sendPageView = () => {
126
+ if (didTrackMount.current) return;
127
+ didTrackMount.current = true;
128
+ void tracker.page();
129
+ };
130
+ if (document.visibilityState === "visible") {
131
+ sendPageView();
132
+ return;
133
+ }
134
+ const onVisibility = () => {
135
+ if (document.visibilityState !== "visible") return;
136
+ document.removeEventListener("visibilitychange", onVisibility);
137
+ sendPageView();
138
+ };
139
+ document.addEventListener("visibilitychange", onVisibility);
140
+ return () => {
141
+ document.removeEventListener("visibilitychange", onVisibility);
142
+ };
146
143
  }, []);
147
144
  return tracker;
148
145
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/tracker.ts","../src/hook.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["export type RestaurantId = string;\n\nexport type ImpressionEvent = {\n schema_version: 1;\n event_id: string;\n ts: string;\n\n restaurant_id: RestaurantId;\n table_no?: number | null;\n\n event_type: string;\n event_detail: Record<string, any>;\n};\n\nexport type TrackerConfig = {\n endpoint: string;\n restaurantId: RestaurantId;\n tableNo?: number;\n headers?: Record<string, string>;\n debug?: boolean;\n disable?: boolean;\n anonIdKey?: string;\n};\n\nfunction uuidv4(): string {\n return crypto.randomUUID();\n}\n\nfunction safeGetLS(key: string): string | null {\n try {\n return localStorage.getItem(key);\n } catch {\n return null;\n }\n}\nfunction safeSetLS(key: string, val: string) {\n try {\n localStorage.setItem(key, val);\n } catch {}\n}\n\nfunction getAnonId(key: string) {\n const existing = safeGetLS(key);\n if (existing) return existing;\n const id = uuidv4();\n safeSetLS(key, id);\n return id;\n}\n\nfunction parseUtm() {\n const p = new URLSearchParams(location.search);\n const source = p.get(\"utm_source\");\n const medium = p.get(\"utm_medium\");\n const campaign = p.get(\"utm_campaign\");\n if (!source && !medium && !campaign) return undefined;\n return { source, medium, campaign };\n}\n\nfunction deviceType(): \"mobile\" | \"tablet\" | \"desktop\" {\n const w = Math.min(screen.width, screen.height);\n if (w <= 480) return \"mobile\";\n if (w <= 1024) return \"tablet\";\n return \"desktop\";\n}\n\nfunction baseDetail(anonId: string) {\n return {\n path: location.pathname + location.search,\n referrer: document.referrer || undefined,\n utm: parseUtm(),\n anon_id: anonId,\n language: navigator.language,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n device: { type: deviceType() },\n screen: { w: window.innerWidth, h: window.innerHeight },\n page: { title: document.title },\n };\n}\n\nexport type Tracker = {\n page: (detail?: Record<string, any>) => Promise<void>;\n track: (eventType: string, detail?: Record<string, any>) => Promise<void>;\n setContext: (\n ctx: Partial<{ restaurantId: RestaurantId; tableNo: number }>\n ) => void;\n disable: () => void;\n enable: () => void;\n};\n\nexport function createTracker(cfg: TrackerConfig): Tracker {\n const isBrowser =\n typeof window !== \"undefined\" &&\n typeof document !== \"undefined\" &&\n typeof navigator !== \"undefined\" &&\n typeof location !== \"undefined\";\n\n if (!isBrowser) {\n return {\n page: async () => {},\n track: async () => {},\n setContext: () => {},\n disable: () => {},\n enable: () => {},\n };\n }\n\n const anonKey = cfg.anonIdKey ?? \"sa_anon_id\";\n const anonId = getAnonId(anonKey);\n\n const state = {\n endpoint: cfg.endpoint,\n restaurantId: cfg.restaurantId,\n tableNo: cfg.tableNo,\n headers: cfg.headers ?? {},\n disabled: !!cfg.disable,\n debug: !!cfg.debug,\n };\n\n async function post(ev: ImpressionEvent) {\n if (state.disabled) return;\n\n if (state.debug) console.log(\"[impr] sending\", ev);\n\n await fetch(state.endpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", ...state.headers },\n body: JSON.stringify(ev),\n keepalive: true,\n });\n }\n\n function beacon(ev: ImpressionEvent) {\n try {\n const blob = new Blob([JSON.stringify(ev)], { type: \"application/json\" });\n navigator.sendBeacon?.(state.endpoint, blob);\n } catch {}\n }\n\n function build(\n eventType: string,\n detail?: Record<string, any>\n ): ImpressionEvent {\n return {\n schema_version: 1,\n event_id: uuidv4(),\n ts: new Date().toISOString(),\n restaurant_id: state.restaurantId,\n table_no: state.tableNo ?? null,\n event_type: eventType,\n event_detail: { ...baseDetail(anonId), ...(detail ?? {}) },\n };\n }\n\n // Unload best-effort\n window.addEventListener(\"pagehide\", () => {\n if (state.disabled) return;\n beacon(build(\"page_view\"));\n });\n\n // SPA navigation tracking (framework-agnostic)\n const origPush = history.pushState;\n history.pushState = function (...args: any) {\n origPush.apply(history, args as any);\n void post(build(\"page_view\"));\n } as any;\n\n const origReplace = history.replaceState;\n history.replaceState = function (...args: any) {\n origReplace.apply(history, args as any);\n void post(build(\"page_view\"));\n } as any;\n\n window.addEventListener(\"popstate\", () => void post(build(\"page_view\")));\n\n return {\n page: async (detail) => post(build(\"page_view\", detail)),\n track: async (eventType, detail) => post(build(eventType, detail)),\n setContext: (ctx) => {\n if (ctx.restaurantId !== undefined) state.restaurantId = ctx.restaurantId;\n if (ctx.tableNo !== undefined) state.tableNo = ctx.tableNo;\n },\n disable: () => {\n state.disabled = true;\n },\n enable: () => {\n state.disabled = false;\n },\n };\n}\n","import { useEffect, useMemo } from \"react\";\nimport { createTracker } from \"./tracker\";\nimport type { TrackerConfig } from \"./tracker\";\n\nexport function useImpressions(config: TrackerConfig) {\n const tracker = useMemo(\n () => createTracker(config),\n [config.endpoint, config.restaurantId, config.tableNo]\n );\n\n useEffect(() => {\n void tracker.page();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return tracker;\n}\n"]}
1
+ {"version":3,"sources":["../src/tracker.ts","../src/hook.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["export type RestaurantId = string;\n\nexport type ImpressionEvent = {\n schema_version: 1;\n event_id: string;\n ts: string;\n\n restaurant_id: RestaurantId;\n table_no?: number | null;\n\n event_type: string;\n event_detail: Record<string, any>;\n};\n\nexport type TrackerConfig = {\n endpoint: string;\n restaurantId: RestaurantId;\n tableNo?: number;\n headers?: Record<string, string>;\n debug?: boolean;\n disable?: boolean;\n anonIdKey?: string;\n};\n\nfunction uuidv4(): string {\n return crypto.randomUUID();\n}\n\nfunction safeGetLS(key: string): string | null {\n try {\n return localStorage.getItem(key);\n } catch {\n return null;\n }\n}\nfunction safeSetLS(key: string, val: string) {\n try {\n localStorage.setItem(key, val);\n } catch {}\n}\n\nfunction getAnonId(key: string) {\n const existing = safeGetLS(key);\n if (existing) return existing;\n const id = uuidv4();\n safeSetLS(key, id);\n return id;\n}\n\nfunction parseUtm() {\n const p = new URLSearchParams(location.search);\n const source = p.get(\"utm_source\");\n const medium = p.get(\"utm_medium\");\n const campaign = p.get(\"utm_campaign\");\n if (!source && !medium && !campaign) return undefined;\n return { source, medium, campaign };\n}\n\nfunction deviceType(): \"mobile\" | \"tablet\" | \"desktop\" {\n const w = Math.min(screen.width, screen.height);\n if (w <= 480) return \"mobile\";\n if (w <= 1024) return \"tablet\";\n return \"desktop\";\n}\n\nfunction baseDetail(anonId: string) {\n return {\n path: location.pathname + location.search,\n referrer: document.referrer || undefined,\n utm: parseUtm(),\n anon_id: anonId,\n language: navigator.language,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n device: { type: deviceType() },\n screen: { w: window.innerWidth, h: window.innerHeight },\n page: { title: document.title },\n };\n}\n\nexport type Tracker = {\n page: (detail?: Record<string, any>) => Promise<void>;\n track: (eventType: string, detail?: Record<string, any>) => Promise<void>;\n setContext: (\n ctx: Partial<{ restaurantId: RestaurantId; tableNo: number }>\n ) => void;\n disable: () => void;\n enable: () => void;\n};\n\nexport function createTracker(cfg: TrackerConfig): Tracker {\n const isBrowser =\n typeof window !== \"undefined\" &&\n typeof document !== \"undefined\" &&\n typeof navigator !== \"undefined\" &&\n typeof location !== \"undefined\";\n\n if (!isBrowser) {\n return {\n page: async () => {},\n track: async () => {},\n setContext: () => {},\n disable: () => {},\n enable: () => {},\n };\n }\n\n const anonKey = cfg.anonIdKey ?? \"sa_anon_id\";\n const anonId = getAnonId(anonKey);\n\n const state = {\n endpoint: cfg.endpoint,\n restaurantId: cfg.restaurantId,\n tableNo: cfg.tableNo,\n headers: cfg.headers ?? {},\n disabled: !!cfg.disable,\n debug: !!cfg.debug,\n };\n\n async function post(ev: ImpressionEvent) {\n if (state.disabled) return;\n\n if (state.debug) console.log(\"[impr] sending\", ev);\n\n await fetch(state.endpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", ...state.headers },\n body: JSON.stringify(ev),\n keepalive: true,\n });\n }\n\n function build(\n eventType: string,\n detail?: Record<string, any>\n ): ImpressionEvent {\n return {\n schema_version: 1,\n event_id: uuidv4(),\n ts: new Date().toISOString(),\n restaurant_id: state.restaurantId,\n table_no: state.tableNo ?? null,\n event_type: eventType,\n event_detail: { ...baseDetail(anonId), ...(detail ?? {}) },\n };\n }\n\n return {\n page: async (detail) => post(build(\"page_view\", detail)),\n track: async (eventType, detail) => post(build(eventType, detail)),\n setContext: (ctx) => {\n if (ctx.restaurantId !== undefined) state.restaurantId = ctx.restaurantId;\n if (ctx.tableNo !== undefined) state.tableNo = ctx.tableNo;\n },\n disable: () => {\n state.disabled = true;\n },\n enable: () => {\n state.disabled = false;\n },\n };\n}\n","import { useEffect, useMemo, useRef } from \"react\";\nimport { createTracker } from \"./tracker\";\nimport type { TrackerConfig } from \"./tracker\";\n\nexport type UseImpressionsOptions = {\n trackOnMount?: boolean;\n};\n\nexport function useImpressions(\n config: TrackerConfig,\n options: UseImpressionsOptions = {}\n) {\n const tracker = useMemo(\n () => createTracker(config),\n [config.endpoint, config.restaurantId, config.tableNo]\n );\n const didTrackMount = useRef(false);\n\n useEffect(() => {\n if (options.trackOnMount === false) return;\n if (didTrackMount.current) return;\n\n const sendPageView = () => {\n if (didTrackMount.current) return;\n didTrackMount.current = true;\n void tracker.page();\n };\n\n if (document.visibilityState === \"visible\") {\n sendPageView();\n return;\n }\n\n const onVisibility = () => {\n if (document.visibilityState !== \"visible\") return;\n document.removeEventListener(\"visibilitychange\", onVisibility);\n sendPageView();\n };\n\n document.addEventListener(\"visibilitychange\", onVisibility);\n return () => {\n document.removeEventListener(\"visibilitychange\", onVisibility);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return tracker;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atmosfer/impressions",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",