@14four/analytics 0.1.1 → 0.1.2

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
@@ -16,13 +16,13 @@ type AnalyticsOptions = ServerOptions | BrowserOptions;
16
16
  /**
17
17
  * Payload for server-side event tracking.
18
18
  * `user_id` is required and used directly as the visitor identifier (no hashing).
19
- * Any additional top-level fields become individual Parquet columns.
19
+ * Custom properties go in `props` and are stored as individual Parquet columns.
20
20
  */
21
21
  type ServerTrackOptions = {
22
22
  user_id: string;
23
23
  url?: string;
24
24
  app_id?: string;
25
- [key: string]: unknown;
25
+ props?: Record<string, string>;
26
26
  };
27
27
  /**
28
28
  * Payload for browser (public) event tracking.
@@ -55,9 +55,9 @@ declare class Analytics {
55
55
  /**
56
56
  * Track an event.
57
57
  *
58
- * **Server mode** — requires `{ user_id }`. Any extra fields become Parquet columns.
58
+ * **Server mode** — requires `{ user_id }`. Custom properties go in `props`.
59
59
  * ```ts
60
- * await analytics.track('signup', { user_id: 'u_123', plan: 'pro' })
60
+ * await analytics.track('signup', { user_id: 'u_123', props: { plan: 'pro' } })
61
61
  * ```
62
62
  *
63
63
  * **Browser mode** — auto-collects url/referrer/screen/language/utm from the browser.
@@ -67,7 +67,7 @@ declare class Analytics {
67
67
  * ```
68
68
  */
69
69
  track(eventName: string, options?: ServerTrackOptions | WebTrackOptions): Promise<void>;
70
- private _post;
70
+ private _send;
71
71
  }
72
72
 
73
73
  export { Analytics, AnalyticsError, type AnalyticsOptions, type BrowserOptions, type ServerOptions, type ServerTrackOptions, type WebTrackOptions, Analytics as default };
package/dist/index.d.ts CHANGED
@@ -16,13 +16,13 @@ type AnalyticsOptions = ServerOptions | BrowserOptions;
16
16
  /**
17
17
  * Payload for server-side event tracking.
18
18
  * `user_id` is required and used directly as the visitor identifier (no hashing).
19
- * Any additional top-level fields become individual Parquet columns.
19
+ * Custom properties go in `props` and are stored as individual Parquet columns.
20
20
  */
21
21
  type ServerTrackOptions = {
22
22
  user_id: string;
23
23
  url?: string;
24
24
  app_id?: string;
25
- [key: string]: unknown;
25
+ props?: Record<string, string>;
26
26
  };
27
27
  /**
28
28
  * Payload for browser (public) event tracking.
@@ -55,9 +55,9 @@ declare class Analytics {
55
55
  /**
56
56
  * Track an event.
57
57
  *
58
- * **Server mode** — requires `{ user_id }`. Any extra fields become Parquet columns.
58
+ * **Server mode** — requires `{ user_id }`. Custom properties go in `props`.
59
59
  * ```ts
60
- * await analytics.track('signup', { user_id: 'u_123', plan: 'pro' })
60
+ * await analytics.track('signup', { user_id: 'u_123', props: { plan: 'pro' } })
61
61
  * ```
62
62
  *
63
63
  * **Browser mode** — auto-collects url/referrer/screen/language/utm from the browser.
@@ -67,7 +67,7 @@ declare class Analytics {
67
67
  * ```
68
68
  */
69
69
  track(eventName: string, options?: ServerTrackOptions | WebTrackOptions): Promise<void>;
70
- private _post;
70
+ private _send;
71
71
  }
72
72
 
73
73
  export { Analytics, AnalyticsError, type AnalyticsOptions, type BrowserOptions, type ServerOptions, type ServerTrackOptions, type WebTrackOptions, Analytics as default };
package/dist/index.js CHANGED
@@ -68,9 +68,9 @@ var Analytics = class {
68
68
  /**
69
69
  * Track an event.
70
70
  *
71
- * **Server mode** — requires `{ user_id }`. Any extra fields become Parquet columns.
71
+ * **Server mode** — requires `{ user_id }`. Custom properties go in `props`.
72
72
  * ```ts
73
- * await analytics.track('signup', { user_id: 'u_123', plan: 'pro' })
73
+ * await analytics.track('signup', { user_id: 'u_123', props: { plan: 'pro' } })
74
74
  * ```
75
75
  *
76
76
  * **Browser mode** — auto-collects url/referrer/screen/language/utm from the browser.
@@ -80,19 +80,16 @@ var Analytics = class {
80
80
  * ```
81
81
  */
82
82
  async track(eventName, options) {
83
- const endpoint = `${this.baseUrl}/api/ingest/event`;
83
+ const params = { event_name: eventName };
84
+ const headers = {};
84
85
  if (this.mode === "server") {
85
- const { user_id, url, app_id, ...customProps } = options ?? {};
86
- const body = {
87
- event_name: eventName,
88
- user_id,
89
- ...customProps
90
- };
91
- if (url !== void 0) body.url = url;
92
- if (app_id !== void 0) body.app_id = app_id;
93
- await this._post(endpoint, body, {
94
- Authorization: `Bearer ${this.apiKey}`
95
- });
86
+ const { user_id, url, app_id, props } = options ?? {};
87
+ params.user_id = user_id;
88
+ if (url !== void 0) params.url = url;
89
+ if (app_id !== void 0) params.app_id = app_id;
90
+ if (props !== void 0 && Object.keys(props).length > 0)
91
+ params.props = JSON.stringify(props);
92
+ headers.Authorization = `Bearer ${this.apiKey}`;
96
93
  } else {
97
94
  const opts = options ?? {};
98
95
  const autoUrl = isBrowser() ? window.location.href : void 0;
@@ -100,33 +97,28 @@ var Analytics = class {
100
97
  const autoScreenWidth = isBrowser() ? window.screen.width : void 0;
101
98
  const autoLanguage = isBrowser() ? navigator.language : void 0;
102
99
  const autoUtm = isBrowser() ? extractUtm(window.location.search) : {};
103
- const body = {
104
- app_id: this.appId,
105
- event_name: eventName,
106
- url: opts.url ?? autoUrl,
107
- ...opts.referrer !== void 0 ? { referrer: opts.referrer } : autoReferrer ? { referrer: autoReferrer } : {},
108
- ...opts.screen_width !== void 0 ? { screen_width: opts.screen_width } : autoScreenWidth !== void 0 ? { screen_width: autoScreenWidth } : {},
109
- ...opts.language !== void 0 ? { language: opts.language } : autoLanguage ? { language: autoLanguage } : {},
110
- ...autoUtm,
111
- ...opts.utm_source !== void 0 && { utm_source: opts.utm_source },
112
- ...opts.utm_medium !== void 0 && { utm_medium: opts.utm_medium },
113
- ...opts.utm_campaign !== void 0 && { utm_campaign: opts.utm_campaign },
114
- ...opts.utm_term !== void 0 && { utm_term: opts.utm_term },
115
- ...opts.utm_content !== void 0 && { utm_content: opts.utm_content },
116
- ...opts.props !== void 0 && { props: opts.props }
117
- };
118
- await this._post(endpoint, body, {});
100
+ params.app_id = this.appId;
101
+ const url = opts.url ?? autoUrl;
102
+ if (url !== void 0) params.url = url;
103
+ const referrer = opts.referrer ?? autoReferrer;
104
+ if (referrer) params.referrer = referrer;
105
+ const screenWidth = opts.screen_width ?? autoScreenWidth;
106
+ if (screenWidth !== void 0) params.screen_width = String(screenWidth);
107
+ const language = opts.language ?? autoLanguage;
108
+ if (language) params.language = language;
109
+ for (const key of ["utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content"]) {
110
+ const val = opts[key] ?? autoUtm[key];
111
+ if (val !== void 0) params[key] = val;
112
+ }
113
+ if (opts.props !== void 0 && Object.keys(opts.props).length > 0)
114
+ params.props = JSON.stringify(opts.props);
119
115
  }
116
+ await this._send(params, headers);
120
117
  }
121
- async _post(url, body, headers) {
122
- const res = await fetch(url, {
123
- method: "POST",
124
- headers: {
125
- "Content-Type": "application/json",
126
- ...headers
127
- },
128
- body: JSON.stringify(body)
129
- });
118
+ async _send(params, headers) {
119
+ const qs = new URLSearchParams(params).toString();
120
+ const url = `${this.baseUrl}/api/ingest/event?${qs}`;
121
+ const res = await fetch(url, { method: "GET", headers });
130
122
  if (!res.ok) {
131
123
  let message = res.statusText;
132
124
  try {
package/dist/index.mjs CHANGED
@@ -42,9 +42,9 @@ var Analytics = class {
42
42
  /**
43
43
  * Track an event.
44
44
  *
45
- * **Server mode** — requires `{ user_id }`. Any extra fields become Parquet columns.
45
+ * **Server mode** — requires `{ user_id }`. Custom properties go in `props`.
46
46
  * ```ts
47
- * await analytics.track('signup', { user_id: 'u_123', plan: 'pro' })
47
+ * await analytics.track('signup', { user_id: 'u_123', props: { plan: 'pro' } })
48
48
  * ```
49
49
  *
50
50
  * **Browser mode** — auto-collects url/referrer/screen/language/utm from the browser.
@@ -54,19 +54,16 @@ var Analytics = class {
54
54
  * ```
55
55
  */
56
56
  async track(eventName, options) {
57
- const endpoint = `${this.baseUrl}/api/ingest/event`;
57
+ const params = { event_name: eventName };
58
+ const headers = {};
58
59
  if (this.mode === "server") {
59
- const { user_id, url, app_id, ...customProps } = options ?? {};
60
- const body = {
61
- event_name: eventName,
62
- user_id,
63
- ...customProps
64
- };
65
- if (url !== void 0) body.url = url;
66
- if (app_id !== void 0) body.app_id = app_id;
67
- await this._post(endpoint, body, {
68
- Authorization: `Bearer ${this.apiKey}`
69
- });
60
+ const { user_id, url, app_id, props } = options ?? {};
61
+ params.user_id = user_id;
62
+ if (url !== void 0) params.url = url;
63
+ if (app_id !== void 0) params.app_id = app_id;
64
+ if (props !== void 0 && Object.keys(props).length > 0)
65
+ params.props = JSON.stringify(props);
66
+ headers.Authorization = `Bearer ${this.apiKey}`;
70
67
  } else {
71
68
  const opts = options ?? {};
72
69
  const autoUrl = isBrowser() ? window.location.href : void 0;
@@ -74,33 +71,28 @@ var Analytics = class {
74
71
  const autoScreenWidth = isBrowser() ? window.screen.width : void 0;
75
72
  const autoLanguage = isBrowser() ? navigator.language : void 0;
76
73
  const autoUtm = isBrowser() ? extractUtm(window.location.search) : {};
77
- const body = {
78
- app_id: this.appId,
79
- event_name: eventName,
80
- url: opts.url ?? autoUrl,
81
- ...opts.referrer !== void 0 ? { referrer: opts.referrer } : autoReferrer ? { referrer: autoReferrer } : {},
82
- ...opts.screen_width !== void 0 ? { screen_width: opts.screen_width } : autoScreenWidth !== void 0 ? { screen_width: autoScreenWidth } : {},
83
- ...opts.language !== void 0 ? { language: opts.language } : autoLanguage ? { language: autoLanguage } : {},
84
- ...autoUtm,
85
- ...opts.utm_source !== void 0 && { utm_source: opts.utm_source },
86
- ...opts.utm_medium !== void 0 && { utm_medium: opts.utm_medium },
87
- ...opts.utm_campaign !== void 0 && { utm_campaign: opts.utm_campaign },
88
- ...opts.utm_term !== void 0 && { utm_term: opts.utm_term },
89
- ...opts.utm_content !== void 0 && { utm_content: opts.utm_content },
90
- ...opts.props !== void 0 && { props: opts.props }
91
- };
92
- await this._post(endpoint, body, {});
74
+ params.app_id = this.appId;
75
+ const url = opts.url ?? autoUrl;
76
+ if (url !== void 0) params.url = url;
77
+ const referrer = opts.referrer ?? autoReferrer;
78
+ if (referrer) params.referrer = referrer;
79
+ const screenWidth = opts.screen_width ?? autoScreenWidth;
80
+ if (screenWidth !== void 0) params.screen_width = String(screenWidth);
81
+ const language = opts.language ?? autoLanguage;
82
+ if (language) params.language = language;
83
+ for (const key of ["utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content"]) {
84
+ const val = opts[key] ?? autoUtm[key];
85
+ if (val !== void 0) params[key] = val;
86
+ }
87
+ if (opts.props !== void 0 && Object.keys(opts.props).length > 0)
88
+ params.props = JSON.stringify(opts.props);
93
89
  }
90
+ await this._send(params, headers);
94
91
  }
95
- async _post(url, body, headers) {
96
- const res = await fetch(url, {
97
- method: "POST",
98
- headers: {
99
- "Content-Type": "application/json",
100
- ...headers
101
- },
102
- body: JSON.stringify(body)
103
- });
92
+ async _send(params, headers) {
93
+ const qs = new URLSearchParams(params).toString();
94
+ const url = `${this.baseUrl}/api/ingest/event?${qs}`;
95
+ const res = await fetch(url, { method: "GET", headers });
104
96
  if (!res.ok) {
105
97
  let message = res.statusText;
106
98
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@14four/analytics",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "14four Analytics SDK — works in Node.js and browser",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",