@xylabs/pixel 5.0.80 → 5.0.82

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
@@ -59,12 +59,12 @@ Event Client for xylabs ESB
59
59
  ### Constructor
60
60
 
61
61
  ```ts
62
- new PixelApi(baseUri): PixelApi;
62
+ new PixelApi(baseUri?): PixelApi;
63
63
  ```
64
64
 
65
65
  ### Parameters
66
66
 
67
- #### baseUri
67
+ #### baseUri?
68
68
 
69
69
  `string` = `'prod'`
70
70
 
@@ -130,20 +130,20 @@ session: string;
130
130
 
131
131
  ```ts
132
132
  toJson():
133
- | undefined
134
133
  | {
135
134
  local: string;
136
135
  session: string;
137
- };
136
+ }
137
+ | undefined;
138
138
  ```
139
139
 
140
140
  ### Returns
141
141
 
142
- \| `undefined`
143
142
  \| \{
144
143
  `local`: `string`;
145
144
  `session`: `string`;
146
145
  \}
146
+ \| `undefined`
147
147
 
148
148
  ### <a id="UniqueUserId"></a>UniqueUserId
149
149
 
@@ -338,12 +338,12 @@ fields: Record<string, string>[] = [];
338
338
  ### getUtmRecord()
339
339
 
340
340
  ```ts
341
- getUtmRecord(): null | Record<string, string>;
341
+ getUtmRecord(): Record<string, string> | null;
342
342
  ```
343
343
 
344
344
  ### Returns
345
345
 
346
- `null` \| `Record`\<`string`, `string`\>
346
+ `Record`\<`string`, `string`\> \| `null`
347
347
 
348
348
  ***
349
349
 
@@ -404,7 +404,7 @@ optional email: string;
404
404
  ### email\_hash?
405
405
 
406
406
  ```ts
407
- optional email_hash: null | string;
407
+ optional email_hash: string | null;
408
408
  ```
409
409
 
410
410
  ***
@@ -514,7 +514,7 @@ eventId?): Promise<void>;
514
514
 
515
515
  #### T
516
516
 
517
- `T` *extends* `JsonObject`
517
+ `T` *extends* `Record`\<`string`, `unknown`\>
518
518
 
519
519
  ### Parameters
520
520
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xylabs/pixel",
3
- "version": "5.0.80",
3
+ "version": "5.0.82",
4
4
  "description": "Event Client for xylabs ESB",
5
5
  "homepage": "https://xylabs.com",
6
6
  "bugs": {
@@ -22,26 +22,23 @@
22
22
  "exports": {
23
23
  ".": {
24
24
  "types": "./dist/browser/index.d.ts",
25
- "source": "./src/index.ts",
26
25
  "default": "./dist/browser/index.mjs"
27
26
  },
28
27
  "./package.json": "./package.json"
29
28
  },
30
29
  "module": "./dist/browser/index.mjs",
31
- "source": "./src/index.ts",
32
30
  "types": "./dist/browser/index.d.ts",
33
31
  "files": [
34
32
  "dist",
35
- "src",
36
33
  "!**/*.bench.*",
37
34
  "!**/*.spec.*",
38
35
  "!**/*.test.*"
39
36
  ],
40
37
  "dependencies": {
41
- "@xylabs/assert": "~5.0.80",
42
- "@xylabs/object": "~5.0.80",
43
- "@xylabs/promise": "~5.0.80",
44
- "@xylabs/typeof": "~5.0.80",
38
+ "@xylabs/assert": "~5.0.82",
39
+ "@xylabs/object": "~5.0.82",
40
+ "@xylabs/promise": "~5.0.82",
41
+ "@xylabs/typeof": "~5.0.82",
45
42
  "async-mutex": "~0.5.0",
46
43
  "bowser": "2.14.1",
47
44
  "fast-deep-equal": "~3.1.3",
@@ -50,11 +47,12 @@
50
47
  },
51
48
  "devDependencies": {
52
49
  "@types/js-cookie": "~3.0.6",
53
- "@types/node": "~25.2.3",
50
+ "@types/node": "~25.4.0",
54
51
  "@types/spark-md5": "~3.0.5",
55
- "@xylabs/ts-scripts-yarn3": "~7.3.2",
56
- "@xylabs/tsconfig-dom": "~7.3.2",
57
- "axios": "^1.13.5",
52
+ "@xylabs/ts-scripts-yarn3": "~7.4.11",
53
+ "@xylabs/tsconfig": "~7.4.11",
54
+ "@xylabs/tsconfig-dom": "~7.4.11",
55
+ "axios": "^1.13.6",
58
56
  "typescript": "~5.9.3",
59
57
  "vitest": "~4.0.18"
60
58
  },
package/src/Api/Api.ts DELETED
@@ -1,23 +0,0 @@
1
- import { isUndefined } from '@xylabs/typeof'
2
- import axios from 'axios'
3
-
4
- import type { UserEvent } from './UserEvent.ts'
5
-
6
- const apiBaseUri: Record<string, string> = {
7
- beta: 'https://pixel.xylabs.com',
8
- local: 'http://localhost:3030',
9
- prod: 'https://pixel.xylabs.com',
10
- }
11
-
12
- export class PixelApi {
13
- private endPoint: string
14
-
15
- /* baseUri can either be a preset (prod, beta, local), or a specific uri */
16
- constructor(baseUri = 'prod') {
17
- this.endPoint = isUndefined(apiBaseUri[baseUri]) ? baseUri : `${apiBaseUri[baseUri]}/t/event/queue`
18
- }
19
-
20
- async trackEvents(events: UserEvent[]) {
21
- return (await axios.post(this.endPoint, events)).data
22
- }
23
- }
@@ -1,22 +0,0 @@
1
- import type { ExIds } from '../ExIds.ts'
2
- import type { UserEventSystem } from './UserEventSystem.ts'
3
-
4
- export interface UserEvent {
5
- cid: string
6
- create_time?: number
7
- email?: string
8
- email_hash?: string
9
- event?: string
10
- event_id?: string
11
- exids?: ExIds
12
- fields?: Record<string, unknown>
13
- host?: string
14
- pathname?: string
15
- pixel?: string
16
- receive_time?: number
17
- referrer?: { local: string; session: string }
18
- rid?: string
19
- system?: UserEventSystem
20
- uid?: string
21
- utm?: Record<string, string>[] | Record<string, string[]>
22
- }
@@ -1,3 +0,0 @@
1
- import type Bowser from 'bowser'
2
-
3
- export type UserEventSystem = Bowser.Parser.ParsedResult
package/src/Api/index.ts DELETED
@@ -1,3 +0,0 @@
1
- export * from './Api.ts'
2
- export * from './UserEvent.ts'
3
- export * from './UserEventSystem.ts'
@@ -1,4 +0,0 @@
1
- export interface CommonFields {
2
- funnel?: string
3
- testData?: string
4
- }
package/src/ExIds.ts DELETED
@@ -1,9 +0,0 @@
1
- export interface ExIds {
2
- fbc?: string
3
- fbp?: string
4
- ga?: string
5
- gclid?: string
6
- rdt_uid?: string
7
- scid?: string
8
- tt_sessionId?: string
9
- }
@@ -1,5 +0,0 @@
1
- import type { CommonFields } from './CommonFields.ts'
2
-
3
- export interface FunnelStartedFields extends CommonFields {
4
- name: string
5
- }
package/src/Pixel.ts DELETED
@@ -1,120 +0,0 @@
1
- import { assertEx } from '@xylabs/assert'
2
- import type { JsonObject } from '@xylabs/object'
3
- import { Mutex } from 'async-mutex'
4
- import Cookies from 'js-cookie'
5
- import md5 from 'spark-md5'
6
-
7
- import type { UserEvent } from './Api/index.ts'
8
- import { PixelApi } from './Api/index.ts'
9
- import type { ExIds } from './ExIds.ts'
10
- import { getSystemInfo } from './getSystemInfo.ts'
11
- import { Referrer } from './Referrer.ts'
12
- import { UniqueUserId } from './UniqueUserId.ts'
13
- import { UtmFields } from './UtmFields.ts'
14
-
15
- const emailHashLocalStorageName = 'xy_email_hash'
16
-
17
- export class XyPixel {
18
- static api = new PixelApi()
19
-
20
- private static _instance?: XyPixel
21
- private static utmFieldsObj: UtmFields
22
-
23
- cid = new UniqueUserId().id
24
- email?: string
25
- email_hash?: string | null
26
- exids?: ExIds
27
- pixelId?: string
28
-
29
- queue: UserEvent[] = []
30
-
31
- private queueMutex = new Mutex()
32
-
33
- private constructor(pixelId: string) {
34
- this.pixelId = pixelId
35
- this.email_hash = localStorage.getItem(emailHashLocalStorageName)
36
- }
37
-
38
- static get instance(): XyPixel {
39
- return assertEx(this._instance, () => 'XyPixel uninitialized')
40
- }
41
-
42
- static init(pixelId: string) {
43
- this._instance = new XyPixel(pixelId)
44
- return this._instance
45
- }
46
-
47
- static selectApi(api: PixelApi) {
48
- this.api = api
49
- }
50
-
51
- private static utmFields = () => {
52
- if (this.utmFieldsObj === undefined) {
53
- this.utmFieldsObj = new UtmFields()
54
- }
55
- return this.utmFieldsObj
56
- }
57
-
58
- identify(email?: string) {
59
- this.email = email
60
- this.email_hash = (email !== undefined && email.length > 0) ? md5.hash(email, true) : undefined
61
- if (this.email_hash !== undefined) {
62
- localStorage.setItem(emailHashLocalStorageName, this.email_hash)
63
- }
64
- }
65
-
66
- async send<T extends JsonObject>(event: string, fields?: T, eventId?: string) {
67
- this.updateFbId()
68
- const utm = XyPixel.utmFields().update()
69
- const referrer = new Referrer()
70
- this.queue.push({
71
- cid: this.cid,
72
- create_time: Date.now(),
73
- email_hash: this.email_hash ?? undefined,
74
- event,
75
- event_id: eventId,
76
- exids: this.exids,
77
- fields,
78
- host: document.location.host,
79
- pathname: document.location.pathname,
80
- pixel: this.pixelId,
81
- referrer: referrer.toJson(),
82
- system: getSystemInfo(),
83
- utm,
84
- })
85
- await this.tryFlushQueue()
86
- }
87
-
88
- private async tryFlushQueue() {
89
- await this.queueMutex.runExclusive(async () => {
90
- if (this.queue.length === 0) return
91
- const api = XyPixel.api
92
- if (api !== undefined) {
93
- const events = this.queue
94
- this.queue = []
95
- try {
96
- await api.trackEvents(events)
97
- } catch (ex) {
98
- if (events !== undefined) {
99
- // put it back since it failed
100
- this.queue = [...this.queue, ...events]
101
- }
102
- // eslint-disable-next-line no-console
103
- console.error(ex)
104
- }
105
- }
106
- })
107
- }
108
-
109
- private updateFbId() {
110
- this.exids = {
111
- fbc: Cookies.get('_fbc'),
112
- fbp: Cookies.get('_fbp'),
113
- ga: Cookies.get('_ga'),
114
- gclid: Cookies.get('_gcl_aw'),
115
- rdt_uid: Cookies.get('rdt_uid'),
116
- scid: Cookies.get('_scid'),
117
- tt_sessionId: sessionStorage.getItem('tt_sessionId') ?? undefined,
118
- }
119
- }
120
- }
@@ -1,8 +0,0 @@
1
- import type { CommonFields } from './CommonFields.ts'
2
-
3
- export interface PurchaseFields extends CommonFields {
4
- id: string
5
- name?: string
6
- price?: number
7
- value?: number
8
- }
package/src/Referrer.ts DELETED
@@ -1,34 +0,0 @@
1
- export class Referrer {
2
- private static storageId = '_coin_referrer'
3
- local: string
4
- session: string
5
- constructor() {
6
- this.session = this.getFromSession() ?? document.referrer
7
- sessionStorage.setItem(Referrer.storageId, this.session)
8
- this.local = this.getFromLocal() ?? document.referrer
9
- globalThis.localStorage.setItem(Referrer.storageId, this.local)
10
- }
11
-
12
- toJson() {
13
- if ((this.local.length > 0) || (this.session.length > 0)) {
14
- return {
15
- local: this.local,
16
- session: this.session,
17
- }
18
- }
19
- }
20
-
21
- private getFromLocal() {
22
- const value = globalThis.localStorage.getItem(Referrer.storageId)
23
- if (value !== null && value.length > 0) {
24
- return value
25
- }
26
- }
27
-
28
- private getFromSession() {
29
- const value = sessionStorage.getItem(Referrer.storageId)
30
- if (value !== null && value.length > 0) {
31
- return value
32
- }
33
- }
34
- }
@@ -1,5 +0,0 @@
1
- import type { CommonFields } from './CommonFields.ts'
2
-
3
- export interface TestStartedFields extends CommonFields {
4
- name: string
5
- }
@@ -1,17 +0,0 @@
1
- export class UniqueUserId {
2
- private static localStorageId = '_coin_cid'
3
- id: string
4
-
5
- constructor() {
6
- this.id = globalThis.localStorage.getItem(UniqueUserId.localStorageId) ?? this.generateId()
7
- globalThis.localStorage.setItem(UniqueUserId.localStorageId, this.id)
8
- }
9
-
10
- toString() {
11
- return this.id
12
- }
13
-
14
- private generateId() {
15
- return crypto.randomUUID()
16
- }
17
- }
@@ -1,8 +0,0 @@
1
- import type { CommonFields } from './CommonFields.ts'
2
-
3
- export interface UserClickFields extends CommonFields {
4
- elementName: string
5
- elementType: string
6
- intent?: string
7
- placement?: string
8
- }
@@ -1,14 +0,0 @@
1
- import type { EmptyObject } from '@xylabs/object'
2
- import type { Promisable } from '@xylabs/promise'
3
-
4
- import type { FunnelStartedFields } from './FunnelStartedFields.ts'
5
- import type { TestStartedFields } from './TestStartedFields.ts'
6
- import type { UserClickFields } from './UserClickFields.ts'
7
- import type { ViewContentFields } from './ViewContentFields.ts'
8
-
9
- export abstract class UserEventHandler<TData extends EmptyObject> {
10
- abstract funnelStarted<T extends TData>(fields: T | FunnelStartedFields): Promisable<void>
11
- abstract testStarted<T extends TData>(fields: T | TestStartedFields): Promisable<void>
12
- abstract userClick<T extends TData>(fields: T | UserClickFields): Promisable<void>
13
- abstract viewContent<T extends TData>(fields: T | ViewContentFields): Promisable<void>
14
- }
package/src/UtmFields.ts DELETED
@@ -1,46 +0,0 @@
1
- import isEqual from 'fast-deep-equal'
2
-
3
- export class UtmFields {
4
- private static localStorageId = '_coin_utm'
5
- fields: Record<string, string>[] = []
6
- constructor() {
7
- const storedString = globalThis.localStorage.getItem(UtmFields.localStorageId) ?? '[]'
8
- try {
9
- this.fields = JSON.parse(storedString)
10
- } catch {
11
- this.fields = []
12
- }
13
- // this clears the old object version if needed
14
- if (!Array.isArray(this.fields)) {
15
- this.fields = []
16
- }
17
- this.update()
18
- globalThis.localStorage.setItem(UtmFields.localStorageId, JSON.stringify(this.fields))
19
- }
20
-
21
- getUtmRecord = () => {
22
- const record: Record<string, string> = {}
23
- const parsedQueryString = document.location.search.split('?')[1]?.split('&') ?? []
24
- for (const item of parsedQueryString) {
25
- const [fullKey, value] = item.split('=')
26
- const [keyCategory, keyName] = fullKey.split('_')
27
- if (keyCategory === 'utm') {
28
- record[keyName] = value
29
- }
30
- }
31
- return Object.keys(record).length > 0 ? record : null
32
- }
33
-
34
- toString() {
35
- return JSON.stringify(this.fields)
36
- }
37
-
38
- // check the query string and if there an new/updated utm values, add them to the fields
39
- update() {
40
- const record = this.getUtmRecord()
41
- if (record && !isEqual(this.fields.at(-1), record)) {
42
- this.fields.push(record)
43
- }
44
- return this.fields ?? undefined
45
- }
46
- }
@@ -1,6 +0,0 @@
1
- import type { CommonFields } from './CommonFields.ts'
2
-
3
- export interface ViewContentFields extends CommonFields {
4
- name: string
5
- path: string
6
- }
@@ -1,20 +0,0 @@
1
- export interface XyLabsTrackingEventJson {
2
- cid: string
3
- create_time?: number
4
- email?: string
5
- email_hash?: string
6
- event?: string
7
- event_id?: string
8
- exids?: Record<string, string>
9
- fields?: Record<string, unknown>
10
- host?: string
11
- ip?: string
12
- pathname?: string
13
- pixel?: string
14
- receive_time?: number
15
- rid?: string
16
- system?: unknown
17
- ua?: string
18
- uid?: string
19
- utm?: Record<string, string>[] | Record<string, string[]>
20
- }
@@ -1,35 +0,0 @@
1
- import { type EmptyObject, toSafeJsonObject } from '@xylabs/object'
2
-
3
- import type { FunnelStartedFields } from './FunnelStartedFields.ts'
4
- import { XyPixel } from './Pixel.ts'
5
- import type { PurchaseFields } from './PurchaseFields.ts'
6
- import type { TestStartedFields } from './TestStartedFields.ts'
7
- import type { UserClickFields } from './UserClickFields.ts'
8
- import { UserEventHandler } from './UserEventHandler.ts'
9
- import type { ViewContentFields } from './ViewContentFields.ts'
10
-
11
- export class XyUserEventHandler<T extends EmptyObject = EmptyObject> extends UserEventHandler<T> {
12
- constructor() {
13
- super()
14
- }
15
-
16
- async funnelStarted(fields: T | FunnelStartedFields) {
17
- return await XyPixel.instance.send('FunnelStarted', toSafeJsonObject(fields, [], 10))
18
- }
19
-
20
- async purchase(fields: T | PurchaseFields) {
21
- return await XyPixel.instance.send('Purchase', toSafeJsonObject(fields, [], 10))
22
- }
23
-
24
- async testStarted(fields: T | TestStartedFields) {
25
- return await XyPixel.instance.send('TestStarted', toSafeJsonObject(fields, [], 10))
26
- }
27
-
28
- async userClick(fields: T | UserClickFields) {
29
- return await XyPixel.instance.send('ViewPage', toSafeJsonObject(fields, [], 10))
30
- }
31
-
32
- async viewContent(fields: T | ViewContentFields) {
33
- return await XyPixel.instance.send('ViewContent', toSafeJsonObject(fields, [], 10))
34
- }
35
- }
@@ -1,15 +0,0 @@
1
- import Bowser from 'bowser'
2
-
3
- import type { UserEventSystem } from './Api/index.ts'
4
-
5
- let systemInfo: UserEventSystem | undefined
6
-
7
- export const getSystemInfo = () => {
8
- try {
9
- systemInfo = systemInfo || Bowser.getParser(globalThis.navigator.userAgent).getResult()
10
- } catch (ex) {
11
- // eslint-disable-next-line no-console
12
- console.log(`getSystemInfo Error: ${ex}`)
13
- }
14
- return systemInfo
15
- }
package/src/index.ts DELETED
@@ -1,14 +0,0 @@
1
- export * from './Api/index.ts'
2
- export * from './CommonFields.ts'
3
- export * from './FunnelStartedFields.ts'
4
- export * from './Pixel.ts'
5
- export * from './PurchaseFields.ts'
6
- export * from './Referrer.ts'
7
- export * from './TestStartedFields.ts'
8
- export * from './UniqueUserId.ts'
9
- export * from './UserClickFields.ts'
10
- export * from './UserEventHandler.ts'
11
- export * from './UtmFields.ts'
12
- export * from './ViewContentFields.ts'
13
- export * from './XyLabsTrackingEventJson.ts'
14
- export * from './XyUserEventHandler.ts'