@yesplz-ai/analytics-react-native 0.1.0 → 0.1.1
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.cjs +24 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -8
- package/dist/index.d.ts +8 -8
- package/dist/index.js +24 -8
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -83,34 +83,41 @@ var GaEventTypeReverse = {
|
|
|
83
83
|
remove_from_wishlist: EventType.UnfavoriteProduct
|
|
84
84
|
};
|
|
85
85
|
var ItemListId = {
|
|
86
|
-
SEARCH_RESULTS: "
|
|
87
|
-
PRODUCT_LIST: "
|
|
88
|
-
YOU_MAY_ALSO_LIKE: "
|
|
89
|
-
COMPLETE_THE_LOOK: "
|
|
90
|
-
COLLABORATIVE_FILTERING: "
|
|
91
|
-
MORE_FROM_BRAND: "
|
|
92
|
-
STYLE_WITH: "
|
|
93
|
-
SHOPPING_CART: "
|
|
86
|
+
SEARCH_RESULTS: "search_results",
|
|
87
|
+
PRODUCT_LIST: "category",
|
|
88
|
+
YOU_MAY_ALSO_LIKE: "rec_YMAL",
|
|
89
|
+
COMPLETE_THE_LOOK: "rec_CTL",
|
|
90
|
+
COLLABORATIVE_FILTERING: "rec_CF",
|
|
91
|
+
MORE_FROM_BRAND: "rec_Brand",
|
|
92
|
+
STYLE_WITH: "STW",
|
|
93
|
+
SHOPPING_CART: "rec_CART",
|
|
94
94
|
ITEM_FOR_YOU: "item-for-you",
|
|
95
95
|
BRAND_FOR_YOU: "brand-for-you"
|
|
96
96
|
};
|
|
97
97
|
var LIST_ID_ALIASES = {
|
|
98
98
|
Search: ItemListId.SEARCH_RESULTS,
|
|
99
|
+
search_results: ItemListId.SEARCH_RESULTS,
|
|
99
100
|
"search-results": ItemListId.SEARCH_RESULTS,
|
|
100
101
|
PLP: ItemListId.PRODUCT_LIST,
|
|
102
|
+
category: ItemListId.PRODUCT_LIST,
|
|
101
103
|
"product-list": ItemListId.PRODUCT_LIST,
|
|
102
104
|
YMAL: ItemListId.YOU_MAY_ALSO_LIKE,
|
|
105
|
+
rec_YMAL: ItemListId.YOU_MAY_ALSO_LIKE,
|
|
103
106
|
"you-may-also-like": ItemListId.YOU_MAY_ALSO_LIKE,
|
|
104
107
|
CTL: ItemListId.COMPLETE_THE_LOOK,
|
|
108
|
+
rec_CTL: ItemListId.COMPLETE_THE_LOOK,
|
|
105
109
|
"complete-the-look": ItemListId.COMPLETE_THE_LOOK,
|
|
106
110
|
CF: ItemListId.COLLABORATIVE_FILTERING,
|
|
111
|
+
rec_CF: ItemListId.COLLABORATIVE_FILTERING,
|
|
107
112
|
"collaborative-filtering": ItemListId.COLLABORATIVE_FILTERING,
|
|
108
113
|
"frequently-bought-together": ItemListId.COLLABORATIVE_FILTERING,
|
|
109
114
|
Brand: ItemListId.MORE_FROM_BRAND,
|
|
115
|
+
rec_Brand: ItemListId.MORE_FROM_BRAND,
|
|
110
116
|
"more-from-brand": ItemListId.MORE_FROM_BRAND,
|
|
111
117
|
STW: ItemListId.STYLE_WITH,
|
|
112
118
|
"style-with": ItemListId.STYLE_WITH,
|
|
113
119
|
CART: ItemListId.SHOPPING_CART,
|
|
120
|
+
rec_CART: ItemListId.SHOPPING_CART,
|
|
114
121
|
"shopping-cart": ItemListId.SHOPPING_CART,
|
|
115
122
|
"item-for-you": ItemListId.ITEM_FOR_YOU,
|
|
116
123
|
"brand-for-you": ItemListId.BRAND_FOR_YOU
|
|
@@ -332,6 +339,7 @@ async function sendToGA(eventType, props, options) {
|
|
|
332
339
|
engagement_time_msec: 1,
|
|
333
340
|
session_engaged: "1"
|
|
334
341
|
};
|
|
342
|
+
if (options.debug) params.debug_mode = true;
|
|
335
343
|
if (currency) params.currency = currency;
|
|
336
344
|
if (value !== void 0) params.value = value;
|
|
337
345
|
if (transaction_id) params.transaction_id = transaction_id;
|
|
@@ -636,6 +644,14 @@ var Analytics = class {
|
|
|
636
644
|
if (props.id && !Array.isArray(props.items)) {
|
|
637
645
|
props.items = [{ item_id: props.id, ...props }];
|
|
638
646
|
}
|
|
647
|
+
if (props.item_list_id) {
|
|
648
|
+
props.item_list_id = normalizeItemListId(props.item_list_id) || void 0;
|
|
649
|
+
}
|
|
650
|
+
if (Array.isArray(props.items)) {
|
|
651
|
+
props.items = props.items.map(
|
|
652
|
+
(item) => item.item_list_id ? { ...item, item_list_id: normalizeItemListId(item.item_list_id) || void 0 } : item
|
|
653
|
+
);
|
|
654
|
+
}
|
|
639
655
|
const metadata = this.collectMetadata();
|
|
640
656
|
Object.assign(props, metadata);
|
|
641
657
|
props.data_provider = "yesplz";
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/analytics.ts","../src/constants.ts","../src/storage.ts","../src/ids.ts","../src/attribution.ts","../src/ga.ts","../src/beacon.ts"],"sourcesContent":["export { analytics, Analytics } from './analytics';\nexport {\n EventType,\n ItemListId,\n normalizeItemListId,\n VERSION,\n} from './constants';\nexport type {\n EventTypeValue,\n ItemListIdValue,\n} from './constants';\nexport type {\n AnalyticsConfig,\n TrackItem,\n TrackProperties,\n ApiEvent,\n EventMetadata,\n} from './types';\n","import { Platform, AppState, type AppStateStatus } from 'react-native';\nimport {\n API_EVENTS,\n EventType,\n GaEventType,\n GaEventTypeReverse,\n VERSION,\n} from './constants';\nimport { Storage, StorageKeys } from './storage';\nimport {\n generateId,\n loadIdentity,\n numericSessionId,\n saveSession,\n saveUser,\n clearUser as clearUserStorage,\n} from './ids';\nimport { handleAttribution } from './attribution';\nimport { sendToGA } from './ga';\nimport { Beacon } from './beacon';\nimport type {\n AnalyticsConfig,\n ApiEvent,\n EventMetadata,\n TrackProperties,\n} from './types';\n\nconst DEFAULT_DEBOUNCE_MS = 1000;\nconst DEFAULT_API_BASE_URL = 'https://api.yesplz.ai';\nconst DEFAULT_GA_PROXY_BASE_URL = 'https://ypsh-admin.yesplz.ai/api/mp/collect';\n\nfunction buildUserAgent(): string {\n const os = Platform.OS;\n const version = Platform.Version;\n return `YesPlzSDK-RN/${VERSION} (${os}; ${String(version)})`;\n}\n\nexport class Analytics {\n private config: Required<\n Pick<AnalyticsConfig, 'debug' | 'debounceMs' | 'cacheUserId' | 'idPrefix'>\n > &\n Omit<AnalyticsConfig, 'debug' | 'debounceMs' | 'cacheUserId' | 'idPrefix'> & {\n appId?: string;\n gaProxyUrl?: string;\n } = {\n debug: false,\n debounceMs: DEFAULT_DEBOUNCE_MS,\n cacheUserId: true,\n idPrefix: '',\n };\n\n private cid: string | null = null;\n private sessionId: string | null = null;\n private userId: string | null = null;\n private userProperties: Record<string, unknown> = {};\n private isInitialized = false;\n private initPromise: Promise<void> | null = null;\n private beacon: Beacon | null = null;\n private pendingTracks: { eventType: string; properties: TrackProperties }[] = [];\n private appStateSubscription: { remove(): void } | null = null;\n\n init(appId: string, config: AnalyticsConfig = {}): Analytics {\n if (this.isInitialized || this.initPromise) return this;\n this.initPromise = this.initInternal(appId, config);\n void this.initPromise;\n return this;\n }\n\n ready(): Promise<void> {\n return this.initPromise ?? Promise.resolve();\n }\n\n private async initInternal(appId: string, config: AnalyticsConfig): Promise<void> {\n const normalizedAppId = String(appId).trim();\n if (!normalizedAppId) {\n throw new Error('[YesPlz Analytics] appId must be a non-empty string');\n }\n\n const apiBaseUrl = (config.apiBaseUrl || DEFAULT_API_BASE_URL).replace(/\\/$/, '');\n const apiEndpoint =\n config.apiEndpoint ||\n `${apiBaseUrl}/api/v1/retailer/${encodeURIComponent(normalizedAppId)}/interactions/`;\n const gaProxyBaseUrl = config.gaProxyBaseUrl || DEFAULT_GA_PROXY_BASE_URL;\n const gaProxySep = gaProxyBaseUrl.includes('?') ? '&' : '?';\n const gaProxyUrl = `${gaProxyBaseUrl}${gaProxySep}shop=${encodeURIComponent(normalizedAppId)}`;\n\n const mergedDefaultParams: Record<string, unknown> = {\n ...(config.defaultParams || {}),\n };\n if (config.testMarker) {\n mergedDefaultParams.test_marker = config.testMarker;\n }\n\n this.config = {\n ...this.config,\n appId: normalizedAppId,\n apiEndpoint,\n apiBaseUrl,\n apiToken: config.apiToken ?? null,\n gaProxyBaseUrl,\n gaProxyUrl,\n idPrefix: config.idPrefix || '',\n defaultParams: mergedDefaultParams,\n testMarker: config.testMarker,\n debug: config.debug ?? false,\n cacheUserId: config.cacheUserId ?? true,\n debounceMs: config.debounceMs || DEFAULT_DEBOUNCE_MS,\n };\n\n const identity = await loadIdentity();\n this.cid = identity.cid;\n this.sessionId = identity.sessionId;\n this.userId = identity.userId;\n this.userProperties = identity.userProperties;\n\n if (config.userId) {\n await this.setUserInternal(config.userId, config.userProperties || {});\n }\n\n if (apiEndpoint) {\n this.beacon = new Beacon({\n apiEndpoint,\n apiToken: this.config.apiToken,\n defaultParams: this.config.defaultParams,\n idPrefix: this.config.idPrefix,\n debounceMs: this.config.debounceMs,\n debug: this.config.debug,\n });\n await this.beacon.restorePending();\n }\n\n this.appStateSubscription = AppState.addEventListener(\n 'change',\n (state: AppStateStatus) => {\n if (state === 'background' || state === 'inactive') {\n void this.beacon?.savePending();\n }\n }\n );\n\n this.isInitialized = true;\n this.log('Initialized');\n\n const queued = this.pendingTracks.splice(0, this.pendingTracks.length);\n for (const item of queued) {\n void this.dispatchTrack(item.eventType, item.properties);\n }\n }\n\n async setUser(\n userId: string | null,\n userProperties: Record<string, unknown> = {}\n ): Promise<Analytics> {\n await this.ready();\n if (userId === null) {\n this.userId = null;\n this.userProperties = {};\n await clearUserStorage();\n this.log('User cleared');\n return this;\n }\n await this.setUserInternal(userId, userProperties);\n return this;\n }\n\n private async setUserInternal(\n userId: string,\n userProperties: Record<string, unknown>\n ): Promise<void> {\n const id = String(userId);\n if (id.length === 0) {\n // eslint-disable-next-line no-console\n console.error('[YesPlz Analytics] User ID must be a non-empty value');\n return;\n }\n this.userId = id;\n this.userProperties = JSON.parse(JSON.stringify(userProperties));\n await saveUser(this.userId, this.userProperties, this.config.cacheUserId);\n this.log(`User set: ${id}`);\n }\n\n getUser(): { userId: string; userProperties: Record<string, unknown> } | null {\n if (!this.userId) return null;\n return { userId: this.userId, userProperties: this.userProperties };\n }\n\n getSessionId(): string | null {\n return this.sessionId;\n }\n\n getClientId(): string | null {\n return this.cid;\n }\n\n track(eventType: string, properties: TrackProperties = {}): Analytics {\n if (typeof eventType !== 'string' || eventType.length === 0) {\n // eslint-disable-next-line no-console\n console.error('[YesPlz Analytics] Event type must be a non-empty string');\n return this;\n }\n\n if (!this.isInitialized) {\n this.pendingTracks.push({\n eventType,\n properties: JSON.parse(JSON.stringify(properties)),\n });\n return this;\n }\n\n void this.dispatchTrack(eventType, properties);\n return this;\n }\n\n private async dispatchTrack(\n eventType: string,\n properties: TrackProperties\n ): Promise<void> {\n const props: TrackProperties = JSON.parse(JSON.stringify(properties));\n\n await handleAttribution(eventType, props, this.config.idPrefix);\n\n if (eventType === EventType.Purchase && !props.transaction_id) {\n props.transaction_id = generateId();\n }\n\n if (props.id && !Array.isArray(props.items)) {\n props.items = [{ item_id: props.id, ...(props as Record<string, unknown>) }];\n }\n\n const metadata = this.collectMetadata();\n Object.assign(props, metadata);\n props.data_provider = 'yesplz';\n if (this.config.testMarker) {\n props.test_marker = this.config.testMarker;\n }\n\n await this.sendGA(eventType, props);\n\n const apiEventType = GaEventTypeReverse[eventType] || eventType;\n if (API_EVENTS.includes(apiEventType)) {\n this.queueApi(apiEventType, props, metadata);\n }\n }\n\n private async sendGA(eventType: string, props: TrackProperties): Promise<void> {\n if (!this.config.gaProxyUrl) return;\n if (!this.cid || !this.sessionId) return;\n\n const gaEventName = GaEventType[eventType] ?? eventType;\n await sendToGA(eventType, props, {\n gaProxyUrl: this.config.gaProxyUrl,\n clientId: this.cid,\n sessionId: this.sessionId,\n numericSessionId: numericSessionId(this.sessionId),\n userId: this.userId,\n debug: this.config.debug,\n });\n this.log(`Track: ${gaEventName}`, props.items?.length ? { items: props.items.length } : undefined);\n }\n\n private queueApi(\n eventType: string,\n props: TrackProperties,\n metadata: EventMetadata\n ): void {\n if (!this.beacon) return;\n const items = props.items && props.items.length > 0 ? props.items : [props];\n const fallbackUrl = `app://${this.config.appId ?? 'yesplz'}/`;\n const url =\n typeof props.page_location === 'string' && props.page_location.length > 0\n ? props.page_location\n : fallbackUrl;\n const referrerUrl =\n typeof props.page_referrer === 'string' && props.page_referrer.length > 0\n ? props.page_referrer\n : null;\n\n const events: ApiEvent[] = items.map((item) => {\n const merged: Record<string, unknown> = {\n ...(props as Record<string, unknown>),\n ...(item as Record<string, unknown>),\n ...metadata,\n };\n const itemId = (item as { item_id?: string }).item_id;\n if (itemId) merged.id = itemId;\n merged.identifier_type = eventType.startsWith('yp_brand_')\n ? 'brand_name'\n : 'product_id';\n\n const event: ApiEvent = {\n event_type: eventType,\n url,\n referrer_url: referrerUrl,\n user_id: this.userId,\n session_id: this.sessionId,\n extra_data: merged,\n };\n if (Object.keys(this.userProperties).length > 0) {\n event.extra_user_data = this.userProperties;\n }\n return event;\n });\n\n this.beacon.enqueueAll(events);\n }\n\n private collectMetadata(): EventMetadata {\n const metadata: EventMetadata = {\n yp_client_time: Date.now(),\n yp_platform: Platform.OS,\n yp_platform_version: String(Platform.Version),\n yp_user_agent: buildUserAgent(),\n yp_timezone_offset: new Date().getTimezoneOffset(),\n };\n try {\n metadata.yp_timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch {\n // ignore\n }\n if (this.cid) metadata.google_client_id = this.cid;\n return metadata;\n }\n\n async flush(): Promise<Analytics> {\n await this.ready();\n await this.beacon?.flush();\n return this;\n }\n\n async reset(): Promise<Analytics> {\n await this.ready();\n this.userId = null;\n this.userProperties = {};\n await clearUserStorage();\n await Storage.removeItem(StorageKeys.PENDING_EVENTS);\n await Storage.removeItem(StorageKeys.ATTRIBUTION);\n const newSession = generateId();\n this.sessionId = newSession;\n await saveSession(newSession);\n this.log('Reset');\n return this;\n }\n\n teardown(): void {\n this.appStateSubscription?.remove();\n this.appStateSubscription = null;\n }\n\n private log(message: string, data?: unknown): void {\n if (this.config.debug) {\n // eslint-disable-next-line no-console\n console.log(`[YesPlz Analytics] ${message}`, data ?? '');\n }\n }\n}\n\nconst globalRef = (globalThis as unknown as { __yesplz_analytics_rn__?: Analytics });\nexport const analytics: Analytics =\n globalRef.__yesplz_analytics_rn__ ||\n (globalRef.__yesplz_analytics_rn__ = new Analytics());\n","export const VERSION = '0.1.0-rn';\n\nexport const EventType = {\n ViewItemList: 'view_item_list',\n ViewItem: 'yp_product_view',\n ViewProduct: 'yp_product_view',\n SelectItem: 'yp_product_select',\n SelectProduct: 'yp_product_select',\n AddToCart: 'yp_product_cart',\n RemoveFromCart: 'yp_product_remove_from_cart',\n BeginCheckout: 'yp_begin_checkout',\n Purchase: 'yp_product_purchase',\n FavoriteProduct: 'yp_product_favorite',\n UnfavoriteProduct: 'yp_product_unfavorite',\n AddToWishlist: 'yp_product_favorite',\n RemoveFromWishlist: 'yp_product_unfavorite',\n ViewBrand: 'yp_brand_view',\n FavoriteBrand: 'yp_brand_favorite',\n UnfavoriteBrand: 'yp_brand_unfavorite',\n} as const;\n\nexport type EventTypeValue = (typeof EventType)[keyof typeof EventType];\n\nexport const GaEventType: Record<string, string> = {\n [EventType.ViewProduct]: 'view_item',\n [EventType.SelectItem]: 'select_item',\n [EventType.AddToCart]: 'add_to_cart',\n [EventType.RemoveFromCart]: 'remove_from_cart',\n [EventType.BeginCheckout]: 'begin_checkout',\n [EventType.Purchase]: 'purchase',\n [EventType.FavoriteProduct]: 'add_to_wishlist',\n [EventType.UnfavoriteProduct]: 'remove_from_wishlist',\n};\n\nexport const GaEventTypeReverse: Record<string, string> = {\n view_item: EventType.ViewProduct,\n select_item: EventType.SelectItem,\n add_to_cart: EventType.AddToCart,\n remove_from_cart: EventType.RemoveFromCart,\n begin_checkout: EventType.BeginCheckout,\n purchase: EventType.Purchase,\n add_to_wishlist: EventType.FavoriteProduct,\n remove_from_wishlist: EventType.UnfavoriteProduct,\n};\n\nexport const ItemListId = {\n SEARCH_RESULTS: 'search-results',\n PRODUCT_LIST: 'product-list',\n YOU_MAY_ALSO_LIKE: 'you-may-also-like',\n COMPLETE_THE_LOOK: 'complete-the-look',\n COLLABORATIVE_FILTERING: 'collaborative-filtering',\n MORE_FROM_BRAND: 'more-from-brand',\n STYLE_WITH: 'style-with',\n SHOPPING_CART: 'shopping-cart',\n ITEM_FOR_YOU: 'item-for-you',\n BRAND_FOR_YOU: 'brand-for-you',\n} as const;\n\nexport type ItemListIdValue = (typeof ItemListId)[keyof typeof ItemListId];\n\nconst LIST_ID_ALIASES: Record<string, string> = {\n Search: ItemListId.SEARCH_RESULTS,\n 'search-results': ItemListId.SEARCH_RESULTS,\n PLP: ItemListId.PRODUCT_LIST,\n 'product-list': ItemListId.PRODUCT_LIST,\n YMAL: ItemListId.YOU_MAY_ALSO_LIKE,\n 'you-may-also-like': ItemListId.YOU_MAY_ALSO_LIKE,\n CTL: ItemListId.COMPLETE_THE_LOOK,\n 'complete-the-look': ItemListId.COMPLETE_THE_LOOK,\n CF: ItemListId.COLLABORATIVE_FILTERING,\n 'collaborative-filtering': ItemListId.COLLABORATIVE_FILTERING,\n 'frequently-bought-together': ItemListId.COLLABORATIVE_FILTERING,\n Brand: ItemListId.MORE_FROM_BRAND,\n 'more-from-brand': ItemListId.MORE_FROM_BRAND,\n STW: ItemListId.STYLE_WITH,\n 'style-with': ItemListId.STYLE_WITH,\n CART: ItemListId.SHOPPING_CART,\n 'shopping-cart': ItemListId.SHOPPING_CART,\n 'item-for-you': ItemListId.ITEM_FOR_YOU,\n 'brand-for-you': ItemListId.BRAND_FOR_YOU,\n};\n\nexport function normalizeItemListId(input: string | undefined | null): string | undefined | null {\n if (!input) return input;\n const alias = LIST_ID_ALIASES[input];\n if (alias) return alias;\n const canonical = Object.values(ItemListId) as string[];\n if (canonical.includes(input)) return input;\n return input;\n}\n\nexport const API_EVENTS: string[] = [\n EventType.ViewProduct,\n EventType.AddToCart,\n EventType.RemoveFromCart,\n EventType.BeginCheckout,\n EventType.Purchase,\n EventType.FavoriteProduct,\n EventType.UnfavoriteProduct,\n EventType.ViewBrand,\n EventType.FavoriteBrand,\n EventType.UnfavoriteBrand,\n];\n","import AsyncStorage from '@react-native-async-storage/async-storage';\n\nexport const StorageKeys = {\n CID: 'yp_cid',\n SESSION: 'yp_session',\n USER_ID: 'yp_user_id',\n USER_PROPS: 'yp_user_props',\n ATTRIBUTION: 'yp_attribution',\n PENDING_EVENTS: 'yp_pending_events',\n} as const;\n\nexport const Storage = {\n async getItem(key: string): Promise<string | null> {\n try {\n return await AsyncStorage.getItem(key);\n } catch {\n return null;\n }\n },\n async setItem(key: string, value: string): Promise<void> {\n try {\n await AsyncStorage.setItem(key, value);\n } catch {\n // ignore\n }\n },\n async removeItem(key: string): Promise<void> {\n try {\n await AsyncStorage.removeItem(key);\n } catch {\n // ignore\n }\n },\n async getJSON<T>(key: string, fallback: T): Promise<T> {\n const raw = await Storage.getItem(key);\n if (!raw) return fallback;\n try {\n return JSON.parse(raw) as T;\n } catch {\n return fallback;\n }\n },\n async setJSON(key: string, value: unknown): Promise<void> {\n try {\n await Storage.setItem(key, JSON.stringify(value));\n } catch {\n // ignore\n }\n },\n};\n","import { Storage, StorageKeys } from './storage';\n\nexport function generateId(): string {\n return Date.now().toString(36) + Math.random().toString(36).substring(2);\n}\n\nexport function hashCode(str: string): number {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n hash = (hash << 5) - hash + str.charCodeAt(i);\n hash |= 0;\n }\n return hash;\n}\n\nexport function numericSessionId(sessionId: string | null | undefined): number {\n if (!sessionId) return Math.floor(Date.now() / 1000);\n return Math.abs(hashCode(sessionId)) || Math.floor(Date.now() / 1000);\n}\n\nexport interface Identity {\n cid: string;\n sessionId: string;\n userId: string | null;\n userProperties: Record<string, unknown>;\n}\n\nexport async function loadIdentity(): Promise<Identity> {\n const [cidStored, sessionStored, userIdStored, userPropsStored] = await Promise.all([\n Storage.getItem(StorageKeys.CID),\n Storage.getItem(StorageKeys.SESSION),\n Storage.getItem(StorageKeys.USER_ID),\n Storage.getItem(StorageKeys.USER_PROPS),\n ]);\n\n let cid = cidStored;\n if (!cid) {\n cid = generateId();\n await Storage.setItem(StorageKeys.CID, cid);\n }\n\n let sessionId = sessionStored;\n if (!sessionId) {\n sessionId = generateId();\n await Storage.setItem(StorageKeys.SESSION, sessionId);\n }\n\n let userProperties: Record<string, unknown> = {};\n if (userPropsStored) {\n try {\n userProperties = JSON.parse(userPropsStored) as Record<string, unknown>;\n } catch {\n userProperties = {};\n }\n }\n\n return { cid, sessionId, userId: userIdStored, userProperties };\n}\n\nexport async function saveCid(cid: string): Promise<void> {\n await Storage.setItem(StorageKeys.CID, cid);\n}\n\nexport async function saveSession(sessionId: string): Promise<void> {\n await Storage.setItem(StorageKeys.SESSION, sessionId);\n}\n\nexport async function saveUser(\n userId: string,\n userProperties: Record<string, unknown>,\n cacheUserId: boolean\n): Promise<void> {\n if (cacheUserId) {\n await Storage.setItem(StorageKeys.USER_ID, userId);\n }\n await Storage.setJSON(StorageKeys.USER_PROPS, userProperties);\n}\n\nexport async function clearUser(): Promise<void> {\n await Storage.removeItem(StorageKeys.USER_ID);\n await Storage.removeItem(StorageKeys.USER_PROPS);\n}\n","import { Storage, StorageKeys } from './storage';\nimport { EventType, GaEventTypeReverse } from './constants';\nimport type { TrackProperties } from './types';\n\nconst EXPIRY_MS = 30 * 60 * 1000;\n\ntype AttributionRecord = { source: string; ts: number };\ntype AttributionStore = Record<string, AttributionRecord>;\n\nfunction normalizeId(rawId: unknown, idPrefix?: string): string | null {\n if (!rawId) return null;\n const idStr = String(rawId);\n if (idPrefix && idStr.startsWith(idPrefix)) {\n return idStr.slice(idPrefix.length);\n }\n const match = idStr.match(/^[a-zA-Z]+-(.+)$/);\n return match ? match[1] : idStr;\n}\n\nasync function loadStore(): Promise<AttributionStore> {\n return Storage.getJSON<AttributionStore>(StorageKeys.ATTRIBUTION, {});\n}\n\nasync function saveStore(store: AttributionStore): Promise<void> {\n await Storage.setJSON(StorageKeys.ATTRIBUTION, store);\n}\n\nfunction pruneExpired(store: AttributionStore): AttributionStore {\n const now = Date.now();\n const next: AttributionStore = {};\n for (const [k, v] of Object.entries(store)) {\n if (now - v.ts <= EXPIRY_MS) next[k] = v;\n }\n return next;\n}\n\nexport async function handleAttribution(\n eventType: string,\n props: TrackProperties,\n idPrefix?: string\n): Promise<void> {\n const normalizedEventType = GaEventTypeReverse[eventType] || eventType;\n\n if (normalizedEventType === EventType.SelectItem) {\n const itemListId = props.item_list_id;\n const rawId = props.id ?? props.items?.[0]?.item_id;\n const productId = normalizeId(rawId, idPrefix);\n if (itemListId && productId) {\n let store = await loadStore();\n store = pruneExpired(store);\n store[productId] = { source: itemListId, ts: Date.now() };\n await saveStore(store);\n }\n return;\n }\n\n if (normalizedEventType === EventType.ViewProduct) {\n const rawId = props.id ?? props.items?.[0]?.item_id;\n const productId = normalizeId(rawId, idPrefix);\n if (!productId) return;\n const store = await loadStore();\n const entry = store[productId];\n if (entry && Date.now() - entry.ts <= EXPIRY_MS) {\n props.item_list_id = entry.source;\n if (Array.isArray(props.items)) {\n props.items = props.items.map((item) => ({ ...item, item_list_id: entry.source }));\n }\n }\n return;\n }\n\n if (normalizedEventType === EventType.AddToCart) {\n if (!Array.isArray(props.items)) return;\n const store = await loadStore();\n props.items = props.items.map((item) => {\n const productId = normalizeId(item.item_id, idPrefix);\n const entry = productId ? store[productId] : null;\n if (entry && Date.now() - entry.ts <= EXPIRY_MS) {\n return { ...item, item_list_id: entry.source };\n }\n return item;\n });\n const firstMatch = props.items.find((item) => item.item_list_id);\n if (firstMatch?.item_list_id) {\n props.item_list_id = firstMatch.item_list_id;\n }\n }\n}\n\nexport async function getAttribution(productId: string): Promise<string | null> {\n const store = await loadStore();\n const entry = store[String(productId)];\n if (entry && Date.now() - entry.ts < EXPIRY_MS) return entry.source;\n return null;\n}\n","import { GaEventType } from './constants';\nimport type { TrackProperties } from './types';\n\nfunction toSnakeCase(str: string): string {\n return str.replace(/-/g, '_');\n}\n\nexport interface GaSendOptions {\n gaProxyUrl: string;\n clientId: string;\n sessionId: string;\n numericSessionId: number;\n userId?: string | null;\n debug?: boolean;\n}\n\nexport async function sendToGA(\n eventType: string,\n props: TrackProperties,\n options: GaSendOptions\n): Promise<void> {\n const gaEvent = GaEventType[eventType] || toSnakeCase(eventType);\n const {\n items,\n currency,\n value,\n transaction_id,\n tax,\n shipping,\n coupon,\n ...rest\n } = props;\n\n const params: Record<string, unknown> = {\n session_id: options.numericSessionId,\n engagement_time_msec: 1,\n session_engaged: '1',\n };\n\n if (currency) params.currency = currency;\n if (value !== undefined) params.value = value;\n if (transaction_id) params.transaction_id = transaction_id;\n if (tax !== undefined) params.tax = tax;\n if (shipping !== undefined) params.shipping = shipping;\n if (coupon) params.coupon = coupon;\n if (items) params.items = items;\n\n const passthroughKeys = [\n 'item_list_id',\n 'data_provider',\n 'event_source',\n 'id',\n 'search_term',\n 'total',\n 'total_text',\n 'total_vector',\n 'page_location',\n 'page_title',\n 'page_referrer',\n 'language',\n 'test_marker',\n 'yp_platform',\n 'yp_platform_version',\n 'yp_user_agent',\n ];\n for (const key of passthroughKeys) {\n if (rest[key] !== undefined) params[key] = rest[key];\n }\n\n const body: Record<string, unknown> = {\n client_id: options.clientId || options.sessionId,\n timestamp_micros: Date.now() * 1000,\n events: [{ name: gaEvent, params }],\n };\n\n if (options.userId) body.user_id = options.userId;\n\n const sep = options.gaProxyUrl.includes('?') ? '&' : '?';\n const url = options.debug\n ? `${options.gaProxyUrl}${sep}debug=1`\n : options.gaProxyUrl;\n\n try {\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n if (options.debug) {\n // eslint-disable-next-line no-console\n console.log(`[YesPlz Analytics] GA MP → ${gaEvent} (status ${res.status})`);\n }\n } catch (e) {\n if (options.debug) {\n // eslint-disable-next-line no-console\n console.log(`[YesPlz Analytics] GA MP error: ${(e as Error).message}`);\n }\n }\n}\n","import { Storage, StorageKeys } from './storage';\nimport type { ApiEvent } from './types';\n\nexport interface BeaconOptions {\n apiEndpoint: string;\n apiToken?: string | null;\n defaultParams?: Record<string, unknown>;\n idPrefix?: string;\n debounceMs?: number;\n debug?: boolean;\n}\n\nexport class Beacon {\n private queue: ApiEvent[] = [];\n private isSending = false;\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(private options: BeaconOptions) {}\n\n enqueue(event: ApiEvent): void {\n this.queue.push(event);\n this.scheduleSend();\n }\n\n enqueueAll(events: ApiEvent[]): void {\n this.queue.push(...events);\n this.scheduleSend();\n }\n\n private scheduleSend(): void {\n if (this.debounceTimer) clearTimeout(this.debounceTimer);\n this.debounceTimer = setTimeout(() => {\n void this.send();\n }, this.options.debounceMs ?? 1000);\n }\n\n async send(retryCount = 0): Promise<void> {\n if (this.queue.length === 0) return;\n if (!this.options.apiEndpoint) return;\n if (this.isSending) return;\n\n this.isSending = true;\n const eventsToSend = this.queue.splice(0, this.queue.length);\n\n const events = eventsToSend.map((event) => {\n const merged: Record<string, unknown> = {\n ...event,\n ...(this.options.defaultParams ?? {}),\n };\n const rawId = (event.extra_data as Record<string, unknown>).id;\n if (rawId && this.options.idPrefix) {\n merged.extra_data = {\n ...event.extra_data,\n id: `${this.options.idPrefix}${rawId}`,\n };\n }\n return merged;\n });\n\n try {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (this.options.apiToken) headers.Authorization = `Token ${this.options.apiToken}`;\n\n const res = await fetch(this.options.apiEndpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify(events),\n });\n\n if (res.status > 299) {\n throw new Error(`Failed to send events (status ${res.status})`);\n }\n\n if (this.options.debug) {\n // eslint-disable-next-line no-console\n console.log(`[YesPlz Analytics] Sync: ${events.length} events sent`);\n }\n await Storage.removeItem(StorageKeys.PENDING_EVENTS);\n } catch (e) {\n if (this.options.debug) {\n // eslint-disable-next-line no-console\n console.log(`[YesPlz Analytics] Sync failed: ${(e as Error).message}`);\n }\n this.queue.unshift(...eventsToSend);\n this.isSending = false;\n if (retryCount < 1) {\n setTimeout(() => void this.send(retryCount + 1), 2000);\n }\n return;\n }\n\n this.isSending = false;\n if (this.queue.length > 0) this.scheduleSend();\n }\n\n async flush(): Promise<void> {\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n await this.send();\n }\n\n async savePending(): Promise<void> {\n if (this.queue.length === 0) return;\n const toSave = this.queue.slice(-100);\n await Storage.setJSON(StorageKeys.PENDING_EVENTS, toSave);\n this.queue = [];\n }\n\n async restorePending(): Promise<void> {\n const pending = await Storage.getJSON<ApiEvent[]>(StorageKeys.PENDING_EVENTS, []);\n if (pending.length > 0) {\n this.queue.unshift(...pending);\n await Storage.removeItem(StorageKeys.PENDING_EVENTS);\n this.scheduleSend();\n }\n }\n}\n"],"mappings":"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","names":["AsyncStorage"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/analytics.ts","../src/constants.ts","../src/storage.ts","../src/ids.ts","../src/attribution.ts","../src/ga.ts","../src/beacon.ts"],"sourcesContent":["export { analytics, Analytics } from './analytics';\nexport {\n EventType,\n ItemListId,\n normalizeItemListId,\n VERSION,\n} from './constants';\nexport type {\n EventTypeValue,\n ItemListIdValue,\n} from './constants';\nexport type {\n AnalyticsConfig,\n TrackItem,\n TrackProperties,\n ApiEvent,\n EventMetadata,\n} from './types';\n","import { Platform, AppState, type AppStateStatus } from 'react-native';\nimport {\n API_EVENTS,\n EventType,\n GaEventType,\n GaEventTypeReverse,\n normalizeItemListId,\n VERSION,\n} from './constants';\nimport { Storage, StorageKeys } from './storage';\nimport {\n generateId,\n loadIdentity,\n numericSessionId,\n saveSession,\n saveUser,\n clearUser as clearUserStorage,\n} from './ids';\nimport { handleAttribution } from './attribution';\nimport { sendToGA } from './ga';\nimport { Beacon } from './beacon';\nimport type {\n AnalyticsConfig,\n ApiEvent,\n EventMetadata,\n TrackProperties,\n} from './types';\n\nconst DEFAULT_DEBOUNCE_MS = 1000;\nconst DEFAULT_API_BASE_URL = 'https://api.yesplz.ai';\nconst DEFAULT_GA_PROXY_BASE_URL = 'https://ypsh-admin.yesplz.ai/api/mp/collect';\n\nfunction buildUserAgent(): string {\n const os = Platform.OS;\n const version = Platform.Version;\n return `YesPlzSDK-RN/${VERSION} (${os}; ${String(version)})`;\n}\n\nexport class Analytics {\n private config: Required<\n Pick<AnalyticsConfig, 'debug' | 'debounceMs' | 'cacheUserId' | 'idPrefix'>\n > &\n Omit<AnalyticsConfig, 'debug' | 'debounceMs' | 'cacheUserId' | 'idPrefix'> & {\n appId?: string;\n gaProxyUrl?: string;\n } = {\n debug: false,\n debounceMs: DEFAULT_DEBOUNCE_MS,\n cacheUserId: true,\n idPrefix: '',\n };\n\n private cid: string | null = null;\n private sessionId: string | null = null;\n private userId: string | null = null;\n private userProperties: Record<string, unknown> = {};\n private isInitialized = false;\n private initPromise: Promise<void> | null = null;\n private beacon: Beacon | null = null;\n private pendingTracks: { eventType: string; properties: TrackProperties }[] = [];\n private appStateSubscription: { remove(): void } | null = null;\n\n init(appId: string, config: AnalyticsConfig = {}): Analytics {\n if (this.isInitialized || this.initPromise) return this;\n this.initPromise = this.initInternal(appId, config);\n void this.initPromise;\n return this;\n }\n\n ready(): Promise<void> {\n return this.initPromise ?? Promise.resolve();\n }\n\n private async initInternal(appId: string, config: AnalyticsConfig): Promise<void> {\n const normalizedAppId = String(appId).trim();\n if (!normalizedAppId) {\n throw new Error('[YesPlz Analytics] appId must be a non-empty string');\n }\n\n const apiBaseUrl = (config.apiBaseUrl || DEFAULT_API_BASE_URL).replace(/\\/$/, '');\n const apiEndpoint =\n config.apiEndpoint ||\n `${apiBaseUrl}/api/v1/retailer/${encodeURIComponent(normalizedAppId)}/interactions/`;\n const gaProxyBaseUrl = config.gaProxyBaseUrl || DEFAULT_GA_PROXY_BASE_URL;\n const gaProxySep = gaProxyBaseUrl.includes('?') ? '&' : '?';\n const gaProxyUrl = `${gaProxyBaseUrl}${gaProxySep}shop=${encodeURIComponent(normalizedAppId)}`;\n\n const mergedDefaultParams: Record<string, unknown> = {\n ...(config.defaultParams || {}),\n };\n if (config.testMarker) {\n mergedDefaultParams.test_marker = config.testMarker;\n }\n\n this.config = {\n ...this.config,\n appId: normalizedAppId,\n apiEndpoint,\n apiBaseUrl,\n apiToken: config.apiToken ?? null,\n gaProxyBaseUrl,\n gaProxyUrl,\n idPrefix: config.idPrefix || '',\n defaultParams: mergedDefaultParams,\n testMarker: config.testMarker,\n debug: config.debug ?? false,\n cacheUserId: config.cacheUserId ?? true,\n debounceMs: config.debounceMs || DEFAULT_DEBOUNCE_MS,\n };\n\n const identity = await loadIdentity();\n this.cid = identity.cid;\n this.sessionId = identity.sessionId;\n this.userId = identity.userId;\n this.userProperties = identity.userProperties;\n\n if (config.userId) {\n await this.setUserInternal(config.userId, config.userProperties || {});\n }\n\n if (apiEndpoint) {\n this.beacon = new Beacon({\n apiEndpoint,\n apiToken: this.config.apiToken,\n defaultParams: this.config.defaultParams,\n idPrefix: this.config.idPrefix,\n debounceMs: this.config.debounceMs,\n debug: this.config.debug,\n });\n await this.beacon.restorePending();\n }\n\n this.appStateSubscription = AppState.addEventListener(\n 'change',\n (state: AppStateStatus) => {\n if (state === 'background' || state === 'inactive') {\n void this.beacon?.savePending();\n }\n }\n );\n\n this.isInitialized = true;\n this.log('Initialized');\n\n const queued = this.pendingTracks.splice(0, this.pendingTracks.length);\n for (const item of queued) {\n void this.dispatchTrack(item.eventType, item.properties);\n }\n }\n\n async setUser(\n userId: string | null,\n userProperties: Record<string, unknown> = {}\n ): Promise<Analytics> {\n await this.ready();\n if (userId === null) {\n this.userId = null;\n this.userProperties = {};\n await clearUserStorage();\n this.log('User cleared');\n return this;\n }\n await this.setUserInternal(userId, userProperties);\n return this;\n }\n\n private async setUserInternal(\n userId: string,\n userProperties: Record<string, unknown>\n ): Promise<void> {\n const id = String(userId);\n if (id.length === 0) {\n // eslint-disable-next-line no-console\n console.error('[YesPlz Analytics] User ID must be a non-empty value');\n return;\n }\n this.userId = id;\n this.userProperties = JSON.parse(JSON.stringify(userProperties));\n await saveUser(this.userId, this.userProperties, this.config.cacheUserId);\n this.log(`User set: ${id}`);\n }\n\n getUser(): { userId: string; userProperties: Record<string, unknown> } | null {\n if (!this.userId) return null;\n return { userId: this.userId, userProperties: this.userProperties };\n }\n\n getSessionId(): string | null {\n return this.sessionId;\n }\n\n getClientId(): string | null {\n return this.cid;\n }\n\n track(eventType: string, properties: TrackProperties = {}): Analytics {\n if (typeof eventType !== 'string' || eventType.length === 0) {\n // eslint-disable-next-line no-console\n console.error('[YesPlz Analytics] Event type must be a non-empty string');\n return this;\n }\n\n if (!this.isInitialized) {\n this.pendingTracks.push({\n eventType,\n properties: JSON.parse(JSON.stringify(properties)),\n });\n return this;\n }\n\n void this.dispatchTrack(eventType, properties);\n return this;\n }\n\n private async dispatchTrack(\n eventType: string,\n properties: TrackProperties\n ): Promise<void> {\n const props: TrackProperties = JSON.parse(JSON.stringify(properties));\n\n await handleAttribution(eventType, props, this.config.idPrefix);\n\n if (eventType === EventType.Purchase && !props.transaction_id) {\n props.transaction_id = generateId();\n }\n\n if (props.id && !Array.isArray(props.items)) {\n props.items = [{ item_id: props.id, ...(props as Record<string, unknown>) }];\n }\n\n if (props.item_list_id) {\n props.item_list_id = normalizeItemListId(props.item_list_id) || undefined;\n }\n if (Array.isArray(props.items)) {\n props.items = props.items.map((item) =>\n item.item_list_id ? { ...item, item_list_id: normalizeItemListId(item.item_list_id) || undefined } : item\n );\n }\n\n const metadata = this.collectMetadata();\n Object.assign(props, metadata);\n props.data_provider = 'yesplz';\n if (this.config.testMarker) {\n props.test_marker = this.config.testMarker;\n }\n\n await this.sendGA(eventType, props);\n\n const apiEventType = GaEventTypeReverse[eventType] || eventType;\n if (API_EVENTS.includes(apiEventType)) {\n this.queueApi(apiEventType, props, metadata);\n }\n }\n\n private async sendGA(eventType: string, props: TrackProperties): Promise<void> {\n if (!this.config.gaProxyUrl) return;\n if (!this.cid || !this.sessionId) return;\n\n const gaEventName = GaEventType[eventType] ?? eventType;\n await sendToGA(eventType, props, {\n gaProxyUrl: this.config.gaProxyUrl,\n clientId: this.cid,\n sessionId: this.sessionId,\n numericSessionId: numericSessionId(this.sessionId),\n userId: this.userId,\n debug: this.config.debug,\n });\n this.log(`Track: ${gaEventName}`, props.items?.length ? { items: props.items.length } : undefined);\n }\n\n private queueApi(\n eventType: string,\n props: TrackProperties,\n metadata: EventMetadata\n ): void {\n if (!this.beacon) return;\n const items = props.items && props.items.length > 0 ? props.items : [props];\n const fallbackUrl = `app://${this.config.appId ?? 'yesplz'}/`;\n const url =\n typeof props.page_location === 'string' && props.page_location.length > 0\n ? props.page_location\n : fallbackUrl;\n const referrerUrl =\n typeof props.page_referrer === 'string' && props.page_referrer.length > 0\n ? props.page_referrer\n : null;\n\n const events: ApiEvent[] = items.map((item) => {\n const merged: Record<string, unknown> = {\n ...(props as Record<string, unknown>),\n ...(item as Record<string, unknown>),\n ...metadata,\n };\n const itemId = (item as { item_id?: string }).item_id;\n if (itemId) merged.id = itemId;\n merged.identifier_type = eventType.startsWith('yp_brand_')\n ? 'brand_name'\n : 'product_id';\n\n const event: ApiEvent = {\n event_type: eventType,\n url,\n referrer_url: referrerUrl,\n user_id: this.userId,\n session_id: this.sessionId,\n extra_data: merged,\n };\n if (Object.keys(this.userProperties).length > 0) {\n event.extra_user_data = this.userProperties;\n }\n return event;\n });\n\n this.beacon.enqueueAll(events);\n }\n\n private collectMetadata(): EventMetadata {\n const metadata: EventMetadata = {\n yp_client_time: Date.now(),\n yp_platform: Platform.OS,\n yp_platform_version: String(Platform.Version),\n yp_user_agent: buildUserAgent(),\n yp_timezone_offset: new Date().getTimezoneOffset(),\n };\n try {\n metadata.yp_timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch {\n // ignore\n }\n if (this.cid) metadata.google_client_id = this.cid;\n return metadata;\n }\n\n async flush(): Promise<Analytics> {\n await this.ready();\n await this.beacon?.flush();\n return this;\n }\n\n async reset(): Promise<Analytics> {\n await this.ready();\n this.userId = null;\n this.userProperties = {};\n await clearUserStorage();\n await Storage.removeItem(StorageKeys.PENDING_EVENTS);\n await Storage.removeItem(StorageKeys.ATTRIBUTION);\n const newSession = generateId();\n this.sessionId = newSession;\n await saveSession(newSession);\n this.log('Reset');\n return this;\n }\n\n teardown(): void {\n this.appStateSubscription?.remove();\n this.appStateSubscription = null;\n }\n\n private log(message: string, data?: unknown): void {\n if (this.config.debug) {\n // eslint-disable-next-line no-console\n console.log(`[YesPlz Analytics] ${message}`, data ?? '');\n }\n }\n}\n\nconst globalRef = (globalThis as unknown as { __yesplz_analytics_rn__?: Analytics });\nexport const analytics: Analytics =\n globalRef.__yesplz_analytics_rn__ ||\n (globalRef.__yesplz_analytics_rn__ = new Analytics());\n","export const VERSION = '0.1.0-rn';\n\nexport const EventType = {\n ViewItemList: 'view_item_list',\n ViewItem: 'yp_product_view',\n ViewProduct: 'yp_product_view',\n SelectItem: 'yp_product_select',\n SelectProduct: 'yp_product_select',\n AddToCart: 'yp_product_cart',\n RemoveFromCart: 'yp_product_remove_from_cart',\n BeginCheckout: 'yp_begin_checkout',\n Purchase: 'yp_product_purchase',\n FavoriteProduct: 'yp_product_favorite',\n UnfavoriteProduct: 'yp_product_unfavorite',\n AddToWishlist: 'yp_product_favorite',\n RemoveFromWishlist: 'yp_product_unfavorite',\n ViewBrand: 'yp_brand_view',\n FavoriteBrand: 'yp_brand_favorite',\n UnfavoriteBrand: 'yp_brand_unfavorite',\n} as const;\n\nexport type EventTypeValue = (typeof EventType)[keyof typeof EventType];\n\nexport const GaEventType: Record<string, string> = {\n [EventType.ViewProduct]: 'view_item',\n [EventType.SelectItem]: 'select_item',\n [EventType.AddToCart]: 'add_to_cart',\n [EventType.RemoveFromCart]: 'remove_from_cart',\n [EventType.BeginCheckout]: 'begin_checkout',\n [EventType.Purchase]: 'purchase',\n [EventType.FavoriteProduct]: 'add_to_wishlist',\n [EventType.UnfavoriteProduct]: 'remove_from_wishlist',\n};\n\nexport const GaEventTypeReverse: Record<string, string> = {\n view_item: EventType.ViewProduct,\n select_item: EventType.SelectItem,\n add_to_cart: EventType.AddToCart,\n remove_from_cart: EventType.RemoveFromCart,\n begin_checkout: EventType.BeginCheckout,\n purchase: EventType.Purchase,\n add_to_wishlist: EventType.FavoriteProduct,\n remove_from_wishlist: EventType.UnfavoriteProduct,\n};\n\nexport const ItemListId = {\n SEARCH_RESULTS: 'search_results',\n PRODUCT_LIST: 'category',\n YOU_MAY_ALSO_LIKE: 'rec_YMAL',\n COMPLETE_THE_LOOK: 'rec_CTL',\n COLLABORATIVE_FILTERING: 'rec_CF',\n MORE_FROM_BRAND: 'rec_Brand',\n STYLE_WITH: 'STW',\n SHOPPING_CART: 'rec_CART',\n ITEM_FOR_YOU: 'item-for-you',\n BRAND_FOR_YOU: 'brand-for-you',\n} as const;\n\nexport type ItemListIdValue = (typeof ItemListId)[keyof typeof ItemListId];\n\nconst LIST_ID_ALIASES: Record<string, string> = {\n Search: ItemListId.SEARCH_RESULTS,\n search_results: ItemListId.SEARCH_RESULTS,\n 'search-results': ItemListId.SEARCH_RESULTS,\n PLP: ItemListId.PRODUCT_LIST,\n category: ItemListId.PRODUCT_LIST,\n 'product-list': ItemListId.PRODUCT_LIST,\n YMAL: ItemListId.YOU_MAY_ALSO_LIKE,\n rec_YMAL: ItemListId.YOU_MAY_ALSO_LIKE,\n 'you-may-also-like': ItemListId.YOU_MAY_ALSO_LIKE,\n CTL: ItemListId.COMPLETE_THE_LOOK,\n rec_CTL: ItemListId.COMPLETE_THE_LOOK,\n 'complete-the-look': ItemListId.COMPLETE_THE_LOOK,\n CF: ItemListId.COLLABORATIVE_FILTERING,\n rec_CF: ItemListId.COLLABORATIVE_FILTERING,\n 'collaborative-filtering': ItemListId.COLLABORATIVE_FILTERING,\n 'frequently-bought-together': ItemListId.COLLABORATIVE_FILTERING,\n Brand: ItemListId.MORE_FROM_BRAND,\n rec_Brand: ItemListId.MORE_FROM_BRAND,\n 'more-from-brand': ItemListId.MORE_FROM_BRAND,\n STW: ItemListId.STYLE_WITH,\n 'style-with': ItemListId.STYLE_WITH,\n CART: ItemListId.SHOPPING_CART,\n rec_CART: ItemListId.SHOPPING_CART,\n 'shopping-cart': ItemListId.SHOPPING_CART,\n 'item-for-you': ItemListId.ITEM_FOR_YOU,\n 'brand-for-you': ItemListId.BRAND_FOR_YOU,\n};\n\nexport function normalizeItemListId(input: string | undefined | null): string | undefined | null {\n if (!input) return input;\n const alias = LIST_ID_ALIASES[input];\n if (alias) return alias;\n const canonical = Object.values(ItemListId) as string[];\n if (canonical.includes(input)) return input;\n return input;\n}\n\nexport const API_EVENTS: string[] = [\n EventType.ViewProduct,\n EventType.AddToCart,\n EventType.RemoveFromCart,\n EventType.BeginCheckout,\n EventType.Purchase,\n EventType.FavoriteProduct,\n EventType.UnfavoriteProduct,\n EventType.ViewBrand,\n EventType.FavoriteBrand,\n EventType.UnfavoriteBrand,\n];\n","import AsyncStorage from '@react-native-async-storage/async-storage';\n\nexport const StorageKeys = {\n CID: 'yp_cid',\n SESSION: 'yp_session',\n USER_ID: 'yp_user_id',\n USER_PROPS: 'yp_user_props',\n ATTRIBUTION: 'yp_attribution',\n PENDING_EVENTS: 'yp_pending_events',\n} as const;\n\nexport const Storage = {\n async getItem(key: string): Promise<string | null> {\n try {\n return await AsyncStorage.getItem(key);\n } catch {\n return null;\n }\n },\n async setItem(key: string, value: string): Promise<void> {\n try {\n await AsyncStorage.setItem(key, value);\n } catch {\n // ignore\n }\n },\n async removeItem(key: string): Promise<void> {\n try {\n await AsyncStorage.removeItem(key);\n } catch {\n // ignore\n }\n },\n async getJSON<T>(key: string, fallback: T): Promise<T> {\n const raw = await Storage.getItem(key);\n if (!raw) return fallback;\n try {\n return JSON.parse(raw) as T;\n } catch {\n return fallback;\n }\n },\n async setJSON(key: string, value: unknown): Promise<void> {\n try {\n await Storage.setItem(key, JSON.stringify(value));\n } catch {\n // ignore\n }\n },\n};\n","import { Storage, StorageKeys } from './storage';\n\nexport function generateId(): string {\n return Date.now().toString(36) + Math.random().toString(36).substring(2);\n}\n\nexport function hashCode(str: string): number {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n hash = (hash << 5) - hash + str.charCodeAt(i);\n hash |= 0;\n }\n return hash;\n}\n\nexport function numericSessionId(sessionId: string | null | undefined): number {\n if (!sessionId) return Math.floor(Date.now() / 1000);\n return Math.abs(hashCode(sessionId)) || Math.floor(Date.now() / 1000);\n}\n\nexport interface Identity {\n cid: string;\n sessionId: string;\n userId: string | null;\n userProperties: Record<string, unknown>;\n}\n\nexport async function loadIdentity(): Promise<Identity> {\n const [cidStored, sessionStored, userIdStored, userPropsStored] = await Promise.all([\n Storage.getItem(StorageKeys.CID),\n Storage.getItem(StorageKeys.SESSION),\n Storage.getItem(StorageKeys.USER_ID),\n Storage.getItem(StorageKeys.USER_PROPS),\n ]);\n\n let cid = cidStored;\n if (!cid) {\n cid = generateId();\n await Storage.setItem(StorageKeys.CID, cid);\n }\n\n let sessionId = sessionStored;\n if (!sessionId) {\n sessionId = generateId();\n await Storage.setItem(StorageKeys.SESSION, sessionId);\n }\n\n let userProperties: Record<string, unknown> = {};\n if (userPropsStored) {\n try {\n userProperties = JSON.parse(userPropsStored) as Record<string, unknown>;\n } catch {\n userProperties = {};\n }\n }\n\n return { cid, sessionId, userId: userIdStored, userProperties };\n}\n\nexport async function saveCid(cid: string): Promise<void> {\n await Storage.setItem(StorageKeys.CID, cid);\n}\n\nexport async function saveSession(sessionId: string): Promise<void> {\n await Storage.setItem(StorageKeys.SESSION, sessionId);\n}\n\nexport async function saveUser(\n userId: string,\n userProperties: Record<string, unknown>,\n cacheUserId: boolean\n): Promise<void> {\n if (cacheUserId) {\n await Storage.setItem(StorageKeys.USER_ID, userId);\n }\n await Storage.setJSON(StorageKeys.USER_PROPS, userProperties);\n}\n\nexport async function clearUser(): Promise<void> {\n await Storage.removeItem(StorageKeys.USER_ID);\n await Storage.removeItem(StorageKeys.USER_PROPS);\n}\n","import { Storage, StorageKeys } from './storage';\nimport { EventType, GaEventTypeReverse } from './constants';\nimport type { TrackProperties } from './types';\n\nconst EXPIRY_MS = 30 * 60 * 1000;\n\ntype AttributionRecord = { source: string; ts: number };\ntype AttributionStore = Record<string, AttributionRecord>;\n\nfunction normalizeId(rawId: unknown, idPrefix?: string): string | null {\n if (!rawId) return null;\n const idStr = String(rawId);\n if (idPrefix && idStr.startsWith(idPrefix)) {\n return idStr.slice(idPrefix.length);\n }\n const match = idStr.match(/^[a-zA-Z]+-(.+)$/);\n return match ? match[1] : idStr;\n}\n\nasync function loadStore(): Promise<AttributionStore> {\n return Storage.getJSON<AttributionStore>(StorageKeys.ATTRIBUTION, {});\n}\n\nasync function saveStore(store: AttributionStore): Promise<void> {\n await Storage.setJSON(StorageKeys.ATTRIBUTION, store);\n}\n\nfunction pruneExpired(store: AttributionStore): AttributionStore {\n const now = Date.now();\n const next: AttributionStore = {};\n for (const [k, v] of Object.entries(store)) {\n if (now - v.ts <= EXPIRY_MS) next[k] = v;\n }\n return next;\n}\n\nexport async function handleAttribution(\n eventType: string,\n props: TrackProperties,\n idPrefix?: string\n): Promise<void> {\n const normalizedEventType = GaEventTypeReverse[eventType] || eventType;\n\n if (normalizedEventType === EventType.SelectItem) {\n const itemListId = props.item_list_id;\n const rawId = props.id ?? props.items?.[0]?.item_id;\n const productId = normalizeId(rawId, idPrefix);\n if (itemListId && productId) {\n let store = await loadStore();\n store = pruneExpired(store);\n store[productId] = { source: itemListId, ts: Date.now() };\n await saveStore(store);\n }\n return;\n }\n\n if (normalizedEventType === EventType.ViewProduct) {\n const rawId = props.id ?? props.items?.[0]?.item_id;\n const productId = normalizeId(rawId, idPrefix);\n if (!productId) return;\n const store = await loadStore();\n const entry = store[productId];\n if (entry && Date.now() - entry.ts <= EXPIRY_MS) {\n props.item_list_id = entry.source;\n if (Array.isArray(props.items)) {\n props.items = props.items.map((item) => ({ ...item, item_list_id: entry.source }));\n }\n }\n return;\n }\n\n if (normalizedEventType === EventType.AddToCart) {\n if (!Array.isArray(props.items)) return;\n const store = await loadStore();\n props.items = props.items.map((item) => {\n const productId = normalizeId(item.item_id, idPrefix);\n const entry = productId ? store[productId] : null;\n if (entry && Date.now() - entry.ts <= EXPIRY_MS) {\n return { ...item, item_list_id: entry.source };\n }\n return item;\n });\n const firstMatch = props.items.find((item) => item.item_list_id);\n if (firstMatch?.item_list_id) {\n props.item_list_id = firstMatch.item_list_id;\n }\n }\n}\n\nexport async function getAttribution(productId: string): Promise<string | null> {\n const store = await loadStore();\n const entry = store[String(productId)];\n if (entry && Date.now() - entry.ts < EXPIRY_MS) return entry.source;\n return null;\n}\n","import { GaEventType } from './constants';\nimport type { TrackProperties } from './types';\n\nfunction toSnakeCase(str: string): string {\n return str.replace(/-/g, '_');\n}\n\nexport interface GaSendOptions {\n gaProxyUrl: string;\n clientId: string;\n sessionId: string;\n numericSessionId: number;\n userId?: string | null;\n debug?: boolean;\n}\n\nexport async function sendToGA(\n eventType: string,\n props: TrackProperties,\n options: GaSendOptions\n): Promise<void> {\n const gaEvent = GaEventType[eventType] || toSnakeCase(eventType);\n const {\n items,\n currency,\n value,\n transaction_id,\n tax,\n shipping,\n coupon,\n ...rest\n } = props;\n\n const params: Record<string, unknown> = {\n session_id: options.numericSessionId,\n engagement_time_msec: 1,\n session_engaged: '1',\n };\n if (options.debug) params.debug_mode = true;\n\n if (currency) params.currency = currency;\n if (value !== undefined) params.value = value;\n if (transaction_id) params.transaction_id = transaction_id;\n if (tax !== undefined) params.tax = tax;\n if (shipping !== undefined) params.shipping = shipping;\n if (coupon) params.coupon = coupon;\n if (items) params.items = items;\n\n const passthroughKeys = [\n 'item_list_id',\n 'data_provider',\n 'event_source',\n 'id',\n 'search_term',\n 'total',\n 'total_text',\n 'total_vector',\n 'page_location',\n 'page_title',\n 'page_referrer',\n 'language',\n 'test_marker',\n 'yp_platform',\n 'yp_platform_version',\n 'yp_user_agent',\n ];\n for (const key of passthroughKeys) {\n if (rest[key] !== undefined) params[key] = rest[key];\n }\n\n const body: Record<string, unknown> = {\n client_id: options.clientId || options.sessionId,\n timestamp_micros: Date.now() * 1000,\n events: [{ name: gaEvent, params }],\n };\n\n if (options.userId) body.user_id = options.userId;\n\n const sep = options.gaProxyUrl.includes('?') ? '&' : '?';\n const url = options.debug\n ? `${options.gaProxyUrl}${sep}debug=1`\n : options.gaProxyUrl;\n\n try {\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n if (options.debug) {\n // eslint-disable-next-line no-console\n console.log(`[YesPlz Analytics] GA MP → ${gaEvent} (status ${res.status})`);\n }\n } catch (e) {\n if (options.debug) {\n // eslint-disable-next-line no-console\n console.log(`[YesPlz Analytics] GA MP error: ${(e as Error).message}`);\n }\n }\n}\n","import { Storage, StorageKeys } from './storage';\nimport type { ApiEvent } from './types';\n\nexport interface BeaconOptions {\n apiEndpoint: string;\n apiToken?: string | null;\n defaultParams?: Record<string, unknown>;\n idPrefix?: string;\n debounceMs?: number;\n debug?: boolean;\n}\n\nexport class Beacon {\n private queue: ApiEvent[] = [];\n private isSending = false;\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(private options: BeaconOptions) {}\n\n enqueue(event: ApiEvent): void {\n this.queue.push(event);\n this.scheduleSend();\n }\n\n enqueueAll(events: ApiEvent[]): void {\n this.queue.push(...events);\n this.scheduleSend();\n }\n\n private scheduleSend(): void {\n if (this.debounceTimer) clearTimeout(this.debounceTimer);\n this.debounceTimer = setTimeout(() => {\n void this.send();\n }, this.options.debounceMs ?? 1000);\n }\n\n async send(retryCount = 0): Promise<void> {\n if (this.queue.length === 0) return;\n if (!this.options.apiEndpoint) return;\n if (this.isSending) return;\n\n this.isSending = true;\n const eventsToSend = this.queue.splice(0, this.queue.length);\n\n const events = eventsToSend.map((event) => {\n const merged: Record<string, unknown> = {\n ...event,\n ...(this.options.defaultParams ?? {}),\n };\n const rawId = (event.extra_data as Record<string, unknown>).id;\n if (rawId && this.options.idPrefix) {\n merged.extra_data = {\n ...event.extra_data,\n id: `${this.options.idPrefix}${rawId}`,\n };\n }\n return merged;\n });\n\n try {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (this.options.apiToken) headers.Authorization = `Token ${this.options.apiToken}`;\n\n const res = await fetch(this.options.apiEndpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify(events),\n });\n\n if (res.status > 299) {\n throw new Error(`Failed to send events (status ${res.status})`);\n }\n\n if (this.options.debug) {\n // eslint-disable-next-line no-console\n console.log(`[YesPlz Analytics] Sync: ${events.length} events sent`);\n }\n await Storage.removeItem(StorageKeys.PENDING_EVENTS);\n } catch (e) {\n if (this.options.debug) {\n // eslint-disable-next-line no-console\n console.log(`[YesPlz Analytics] Sync failed: ${(e as Error).message}`);\n }\n this.queue.unshift(...eventsToSend);\n this.isSending = false;\n if (retryCount < 1) {\n setTimeout(() => void this.send(retryCount + 1), 2000);\n }\n return;\n }\n\n this.isSending = false;\n if (this.queue.length > 0) this.scheduleSend();\n }\n\n async flush(): Promise<void> {\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n await this.send();\n }\n\n async savePending(): Promise<void> {\n if (this.queue.length === 0) return;\n const toSave = this.queue.slice(-100);\n await Storage.setJSON(StorageKeys.PENDING_EVENTS, toSave);\n this.queue = [];\n }\n\n async restorePending(): Promise<void> {\n const pending = await Storage.getJSON<ApiEvent[]>(StorageKeys.PENDING_EVENTS, []);\n if (pending.length > 0) {\n this.queue.unshift(...pending);\n await Storage.removeItem(StorageKeys.PENDING_EVENTS);\n this.scheduleSend();\n }\n }\n}\n"],"mappings":"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","names":["AsyncStorage"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -113,14 +113,14 @@ declare const EventType: {
|
|
|
113
113
|
};
|
|
114
114
|
type EventTypeValue = (typeof EventType)[keyof typeof EventType];
|
|
115
115
|
declare const ItemListId: {
|
|
116
|
-
readonly SEARCH_RESULTS: "
|
|
117
|
-
readonly PRODUCT_LIST: "
|
|
118
|
-
readonly YOU_MAY_ALSO_LIKE: "
|
|
119
|
-
readonly COMPLETE_THE_LOOK: "
|
|
120
|
-
readonly COLLABORATIVE_FILTERING: "
|
|
121
|
-
readonly MORE_FROM_BRAND: "
|
|
122
|
-
readonly STYLE_WITH: "
|
|
123
|
-
readonly SHOPPING_CART: "
|
|
116
|
+
readonly SEARCH_RESULTS: "search_results";
|
|
117
|
+
readonly PRODUCT_LIST: "category";
|
|
118
|
+
readonly YOU_MAY_ALSO_LIKE: "rec_YMAL";
|
|
119
|
+
readonly COMPLETE_THE_LOOK: "rec_CTL";
|
|
120
|
+
readonly COLLABORATIVE_FILTERING: "rec_CF";
|
|
121
|
+
readonly MORE_FROM_BRAND: "rec_Brand";
|
|
122
|
+
readonly STYLE_WITH: "STW";
|
|
123
|
+
readonly SHOPPING_CART: "rec_CART";
|
|
124
124
|
readonly ITEM_FOR_YOU: "item-for-you";
|
|
125
125
|
readonly BRAND_FOR_YOU: "brand-for-you";
|
|
126
126
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -113,14 +113,14 @@ declare const EventType: {
|
|
|
113
113
|
};
|
|
114
114
|
type EventTypeValue = (typeof EventType)[keyof typeof EventType];
|
|
115
115
|
declare const ItemListId: {
|
|
116
|
-
readonly SEARCH_RESULTS: "
|
|
117
|
-
readonly PRODUCT_LIST: "
|
|
118
|
-
readonly YOU_MAY_ALSO_LIKE: "
|
|
119
|
-
readonly COMPLETE_THE_LOOK: "
|
|
120
|
-
readonly COLLABORATIVE_FILTERING: "
|
|
121
|
-
readonly MORE_FROM_BRAND: "
|
|
122
|
-
readonly STYLE_WITH: "
|
|
123
|
-
readonly SHOPPING_CART: "
|
|
116
|
+
readonly SEARCH_RESULTS: "search_results";
|
|
117
|
+
readonly PRODUCT_LIST: "category";
|
|
118
|
+
readonly YOU_MAY_ALSO_LIKE: "rec_YMAL";
|
|
119
|
+
readonly COMPLETE_THE_LOOK: "rec_CTL";
|
|
120
|
+
readonly COLLABORATIVE_FILTERING: "rec_CF";
|
|
121
|
+
readonly MORE_FROM_BRAND: "rec_Brand";
|
|
122
|
+
readonly STYLE_WITH: "STW";
|
|
123
|
+
readonly SHOPPING_CART: "rec_CART";
|
|
124
124
|
readonly ITEM_FOR_YOU: "item-for-you";
|
|
125
125
|
readonly BRAND_FOR_YOU: "brand-for-you";
|
|
126
126
|
};
|
package/dist/index.js
CHANGED
|
@@ -42,34 +42,41 @@ var GaEventTypeReverse = {
|
|
|
42
42
|
remove_from_wishlist: EventType.UnfavoriteProduct
|
|
43
43
|
};
|
|
44
44
|
var ItemListId = {
|
|
45
|
-
SEARCH_RESULTS: "
|
|
46
|
-
PRODUCT_LIST: "
|
|
47
|
-
YOU_MAY_ALSO_LIKE: "
|
|
48
|
-
COMPLETE_THE_LOOK: "
|
|
49
|
-
COLLABORATIVE_FILTERING: "
|
|
50
|
-
MORE_FROM_BRAND: "
|
|
51
|
-
STYLE_WITH: "
|
|
52
|
-
SHOPPING_CART: "
|
|
45
|
+
SEARCH_RESULTS: "search_results",
|
|
46
|
+
PRODUCT_LIST: "category",
|
|
47
|
+
YOU_MAY_ALSO_LIKE: "rec_YMAL",
|
|
48
|
+
COMPLETE_THE_LOOK: "rec_CTL",
|
|
49
|
+
COLLABORATIVE_FILTERING: "rec_CF",
|
|
50
|
+
MORE_FROM_BRAND: "rec_Brand",
|
|
51
|
+
STYLE_WITH: "STW",
|
|
52
|
+
SHOPPING_CART: "rec_CART",
|
|
53
53
|
ITEM_FOR_YOU: "item-for-you",
|
|
54
54
|
BRAND_FOR_YOU: "brand-for-you"
|
|
55
55
|
};
|
|
56
56
|
var LIST_ID_ALIASES = {
|
|
57
57
|
Search: ItemListId.SEARCH_RESULTS,
|
|
58
|
+
search_results: ItemListId.SEARCH_RESULTS,
|
|
58
59
|
"search-results": ItemListId.SEARCH_RESULTS,
|
|
59
60
|
PLP: ItemListId.PRODUCT_LIST,
|
|
61
|
+
category: ItemListId.PRODUCT_LIST,
|
|
60
62
|
"product-list": ItemListId.PRODUCT_LIST,
|
|
61
63
|
YMAL: ItemListId.YOU_MAY_ALSO_LIKE,
|
|
64
|
+
rec_YMAL: ItemListId.YOU_MAY_ALSO_LIKE,
|
|
62
65
|
"you-may-also-like": ItemListId.YOU_MAY_ALSO_LIKE,
|
|
63
66
|
CTL: ItemListId.COMPLETE_THE_LOOK,
|
|
67
|
+
rec_CTL: ItemListId.COMPLETE_THE_LOOK,
|
|
64
68
|
"complete-the-look": ItemListId.COMPLETE_THE_LOOK,
|
|
65
69
|
CF: ItemListId.COLLABORATIVE_FILTERING,
|
|
70
|
+
rec_CF: ItemListId.COLLABORATIVE_FILTERING,
|
|
66
71
|
"collaborative-filtering": ItemListId.COLLABORATIVE_FILTERING,
|
|
67
72
|
"frequently-bought-together": ItemListId.COLLABORATIVE_FILTERING,
|
|
68
73
|
Brand: ItemListId.MORE_FROM_BRAND,
|
|
74
|
+
rec_Brand: ItemListId.MORE_FROM_BRAND,
|
|
69
75
|
"more-from-brand": ItemListId.MORE_FROM_BRAND,
|
|
70
76
|
STW: ItemListId.STYLE_WITH,
|
|
71
77
|
"style-with": ItemListId.STYLE_WITH,
|
|
72
78
|
CART: ItemListId.SHOPPING_CART,
|
|
79
|
+
rec_CART: ItemListId.SHOPPING_CART,
|
|
73
80
|
"shopping-cart": ItemListId.SHOPPING_CART,
|
|
74
81
|
"item-for-you": ItemListId.ITEM_FOR_YOU,
|
|
75
82
|
"brand-for-you": ItemListId.BRAND_FOR_YOU
|
|
@@ -291,6 +298,7 @@ async function sendToGA(eventType, props, options) {
|
|
|
291
298
|
engagement_time_msec: 1,
|
|
292
299
|
session_engaged: "1"
|
|
293
300
|
};
|
|
301
|
+
if (options.debug) params.debug_mode = true;
|
|
294
302
|
if (currency) params.currency = currency;
|
|
295
303
|
if (value !== void 0) params.value = value;
|
|
296
304
|
if (transaction_id) params.transaction_id = transaction_id;
|
|
@@ -595,6 +603,14 @@ var Analytics = class {
|
|
|
595
603
|
if (props.id && !Array.isArray(props.items)) {
|
|
596
604
|
props.items = [{ item_id: props.id, ...props }];
|
|
597
605
|
}
|
|
606
|
+
if (props.item_list_id) {
|
|
607
|
+
props.item_list_id = normalizeItemListId(props.item_list_id) || void 0;
|
|
608
|
+
}
|
|
609
|
+
if (Array.isArray(props.items)) {
|
|
610
|
+
props.items = props.items.map(
|
|
611
|
+
(item) => item.item_list_id ? { ...item, item_list_id: normalizeItemListId(item.item_list_id) || void 0 } : item
|
|
612
|
+
);
|
|
613
|
+
}
|
|
598
614
|
const metadata = this.collectMetadata();
|
|
599
615
|
Object.assign(props, metadata);
|
|
600
616
|
props.data_provider = "yesplz";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/analytics.ts","../src/constants.ts","../src/storage.ts","../src/ids.ts","../src/attribution.ts","../src/ga.ts","../src/beacon.ts"],"sourcesContent":["import { Platform, AppState, type AppStateStatus } from 'react-native';\nimport {\n API_EVENTS,\n EventType,\n GaEventType,\n GaEventTypeReverse,\n VERSION,\n} from './constants';\nimport { Storage, StorageKeys } from './storage';\nimport {\n generateId,\n loadIdentity,\n numericSessionId,\n saveSession,\n saveUser,\n clearUser as clearUserStorage,\n} from './ids';\nimport { handleAttribution } from './attribution';\nimport { sendToGA } from './ga';\nimport { Beacon } from './beacon';\nimport type {\n AnalyticsConfig,\n ApiEvent,\n EventMetadata,\n TrackProperties,\n} from './types';\n\nconst DEFAULT_DEBOUNCE_MS = 1000;\nconst DEFAULT_API_BASE_URL = 'https://api.yesplz.ai';\nconst DEFAULT_GA_PROXY_BASE_URL = 'https://ypsh-admin.yesplz.ai/api/mp/collect';\n\nfunction buildUserAgent(): string {\n const os = Platform.OS;\n const version = Platform.Version;\n return `YesPlzSDK-RN/${VERSION} (${os}; ${String(version)})`;\n}\n\nexport class Analytics {\n private config: Required<\n Pick<AnalyticsConfig, 'debug' | 'debounceMs' | 'cacheUserId' | 'idPrefix'>\n > &\n Omit<AnalyticsConfig, 'debug' | 'debounceMs' | 'cacheUserId' | 'idPrefix'> & {\n appId?: string;\n gaProxyUrl?: string;\n } = {\n debug: false,\n debounceMs: DEFAULT_DEBOUNCE_MS,\n cacheUserId: true,\n idPrefix: '',\n };\n\n private cid: string | null = null;\n private sessionId: string | null = null;\n private userId: string | null = null;\n private userProperties: Record<string, unknown> = {};\n private isInitialized = false;\n private initPromise: Promise<void> | null = null;\n private beacon: Beacon | null = null;\n private pendingTracks: { eventType: string; properties: TrackProperties }[] = [];\n private appStateSubscription: { remove(): void } | null = null;\n\n init(appId: string, config: AnalyticsConfig = {}): Analytics {\n if (this.isInitialized || this.initPromise) return this;\n this.initPromise = this.initInternal(appId, config);\n void this.initPromise;\n return this;\n }\n\n ready(): Promise<void> {\n return this.initPromise ?? Promise.resolve();\n }\n\n private async initInternal(appId: string, config: AnalyticsConfig): Promise<void> {\n const normalizedAppId = String(appId).trim();\n if (!normalizedAppId) {\n throw new Error('[YesPlz Analytics] appId must be a non-empty string');\n }\n\n const apiBaseUrl = (config.apiBaseUrl || DEFAULT_API_BASE_URL).replace(/\\/$/, '');\n const apiEndpoint =\n config.apiEndpoint ||\n `${apiBaseUrl}/api/v1/retailer/${encodeURIComponent(normalizedAppId)}/interactions/`;\n const gaProxyBaseUrl = config.gaProxyBaseUrl || DEFAULT_GA_PROXY_BASE_URL;\n const gaProxySep = gaProxyBaseUrl.includes('?') ? '&' : '?';\n const gaProxyUrl = `${gaProxyBaseUrl}${gaProxySep}shop=${encodeURIComponent(normalizedAppId)}`;\n\n const mergedDefaultParams: Record<string, unknown> = {\n ...(config.defaultParams || {}),\n };\n if (config.testMarker) {\n mergedDefaultParams.test_marker = config.testMarker;\n }\n\n this.config = {\n ...this.config,\n appId: normalizedAppId,\n apiEndpoint,\n apiBaseUrl,\n apiToken: config.apiToken ?? null,\n gaProxyBaseUrl,\n gaProxyUrl,\n idPrefix: config.idPrefix || '',\n defaultParams: mergedDefaultParams,\n testMarker: config.testMarker,\n debug: config.debug ?? false,\n cacheUserId: config.cacheUserId ?? true,\n debounceMs: config.debounceMs || DEFAULT_DEBOUNCE_MS,\n };\n\n const identity = await loadIdentity();\n this.cid = identity.cid;\n this.sessionId = identity.sessionId;\n this.userId = identity.userId;\n this.userProperties = identity.userProperties;\n\n if (config.userId) {\n await this.setUserInternal(config.userId, config.userProperties || {});\n }\n\n if (apiEndpoint) {\n this.beacon = new Beacon({\n apiEndpoint,\n apiToken: this.config.apiToken,\n defaultParams: this.config.defaultParams,\n idPrefix: this.config.idPrefix,\n debounceMs: this.config.debounceMs,\n debug: this.config.debug,\n });\n await this.beacon.restorePending();\n }\n\n this.appStateSubscription = AppState.addEventListener(\n 'change',\n (state: AppStateStatus) => {\n if (state === 'background' || state === 'inactive') {\n void this.beacon?.savePending();\n }\n }\n );\n\n this.isInitialized = true;\n this.log('Initialized');\n\n const queued = this.pendingTracks.splice(0, this.pendingTracks.length);\n for (const item of queued) {\n void this.dispatchTrack(item.eventType, item.properties);\n }\n }\n\n async setUser(\n userId: string | null,\n userProperties: Record<string, unknown> = {}\n ): Promise<Analytics> {\n await this.ready();\n if (userId === null) {\n this.userId = null;\n this.userProperties = {};\n await clearUserStorage();\n this.log('User cleared');\n return this;\n }\n await this.setUserInternal(userId, userProperties);\n return this;\n }\n\n private async setUserInternal(\n userId: string,\n userProperties: Record<string, unknown>\n ): Promise<void> {\n const id = String(userId);\n if (id.length === 0) {\n // eslint-disable-next-line no-console\n console.error('[YesPlz Analytics] User ID must be a non-empty value');\n return;\n }\n this.userId = id;\n this.userProperties = JSON.parse(JSON.stringify(userProperties));\n await saveUser(this.userId, this.userProperties, this.config.cacheUserId);\n this.log(`User set: ${id}`);\n }\n\n getUser(): { userId: string; userProperties: Record<string, unknown> } | null {\n if (!this.userId) return null;\n return { userId: this.userId, userProperties: this.userProperties };\n }\n\n getSessionId(): string | null {\n return this.sessionId;\n }\n\n getClientId(): string | null {\n return this.cid;\n }\n\n track(eventType: string, properties: TrackProperties = {}): Analytics {\n if (typeof eventType !== 'string' || eventType.length === 0) {\n // eslint-disable-next-line no-console\n console.error('[YesPlz Analytics] Event type must be a non-empty string');\n return this;\n }\n\n if (!this.isInitialized) {\n this.pendingTracks.push({\n eventType,\n properties: JSON.parse(JSON.stringify(properties)),\n });\n return this;\n }\n\n void this.dispatchTrack(eventType, properties);\n return this;\n }\n\n private async dispatchTrack(\n eventType: string,\n properties: TrackProperties\n ): Promise<void> {\n const props: TrackProperties = JSON.parse(JSON.stringify(properties));\n\n await handleAttribution(eventType, props, this.config.idPrefix);\n\n if (eventType === EventType.Purchase && !props.transaction_id) {\n props.transaction_id = generateId();\n }\n\n if (props.id && !Array.isArray(props.items)) {\n props.items = [{ item_id: props.id, ...(props as Record<string, unknown>) }];\n }\n\n const metadata = this.collectMetadata();\n Object.assign(props, metadata);\n props.data_provider = 'yesplz';\n if (this.config.testMarker) {\n props.test_marker = this.config.testMarker;\n }\n\n await this.sendGA(eventType, props);\n\n const apiEventType = GaEventTypeReverse[eventType] || eventType;\n if (API_EVENTS.includes(apiEventType)) {\n this.queueApi(apiEventType, props, metadata);\n }\n }\n\n private async sendGA(eventType: string, props: TrackProperties): Promise<void> {\n if (!this.config.gaProxyUrl) return;\n if (!this.cid || !this.sessionId) return;\n\n const gaEventName = GaEventType[eventType] ?? eventType;\n await sendToGA(eventType, props, {\n gaProxyUrl: this.config.gaProxyUrl,\n clientId: this.cid,\n sessionId: this.sessionId,\n numericSessionId: numericSessionId(this.sessionId),\n userId: this.userId,\n debug: this.config.debug,\n });\n this.log(`Track: ${gaEventName}`, props.items?.length ? { items: props.items.length } : undefined);\n }\n\n private queueApi(\n eventType: string,\n props: TrackProperties,\n metadata: EventMetadata\n ): void {\n if (!this.beacon) return;\n const items = props.items && props.items.length > 0 ? props.items : [props];\n const fallbackUrl = `app://${this.config.appId ?? 'yesplz'}/`;\n const url =\n typeof props.page_location === 'string' && props.page_location.length > 0\n ? props.page_location\n : fallbackUrl;\n const referrerUrl =\n typeof props.page_referrer === 'string' && props.page_referrer.length > 0\n ? props.page_referrer\n : null;\n\n const events: ApiEvent[] = items.map((item) => {\n const merged: Record<string, unknown> = {\n ...(props as Record<string, unknown>),\n ...(item as Record<string, unknown>),\n ...metadata,\n };\n const itemId = (item as { item_id?: string }).item_id;\n if (itemId) merged.id = itemId;\n merged.identifier_type = eventType.startsWith('yp_brand_')\n ? 'brand_name'\n : 'product_id';\n\n const event: ApiEvent = {\n event_type: eventType,\n url,\n referrer_url: referrerUrl,\n user_id: this.userId,\n session_id: this.sessionId,\n extra_data: merged,\n };\n if (Object.keys(this.userProperties).length > 0) {\n event.extra_user_data = this.userProperties;\n }\n return event;\n });\n\n this.beacon.enqueueAll(events);\n }\n\n private collectMetadata(): EventMetadata {\n const metadata: EventMetadata = {\n yp_client_time: Date.now(),\n yp_platform: Platform.OS,\n yp_platform_version: String(Platform.Version),\n yp_user_agent: buildUserAgent(),\n yp_timezone_offset: new Date().getTimezoneOffset(),\n };\n try {\n metadata.yp_timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch {\n // ignore\n }\n if (this.cid) metadata.google_client_id = this.cid;\n return metadata;\n }\n\n async flush(): Promise<Analytics> {\n await this.ready();\n await this.beacon?.flush();\n return this;\n }\n\n async reset(): Promise<Analytics> {\n await this.ready();\n this.userId = null;\n this.userProperties = {};\n await clearUserStorage();\n await Storage.removeItem(StorageKeys.PENDING_EVENTS);\n await Storage.removeItem(StorageKeys.ATTRIBUTION);\n const newSession = generateId();\n this.sessionId = newSession;\n await saveSession(newSession);\n this.log('Reset');\n return this;\n }\n\n teardown(): void {\n this.appStateSubscription?.remove();\n this.appStateSubscription = null;\n }\n\n private log(message: string, data?: unknown): void {\n if (this.config.debug) {\n // eslint-disable-next-line no-console\n console.log(`[YesPlz Analytics] ${message}`, data ?? '');\n }\n }\n}\n\nconst globalRef = (globalThis as unknown as { __yesplz_analytics_rn__?: Analytics });\nexport const analytics: Analytics =\n globalRef.__yesplz_analytics_rn__ ||\n (globalRef.__yesplz_analytics_rn__ = new Analytics());\n","export const VERSION = '0.1.0-rn';\n\nexport const EventType = {\n ViewItemList: 'view_item_list',\n ViewItem: 'yp_product_view',\n ViewProduct: 'yp_product_view',\n SelectItem: 'yp_product_select',\n SelectProduct: 'yp_product_select',\n AddToCart: 'yp_product_cart',\n RemoveFromCart: 'yp_product_remove_from_cart',\n BeginCheckout: 'yp_begin_checkout',\n Purchase: 'yp_product_purchase',\n FavoriteProduct: 'yp_product_favorite',\n UnfavoriteProduct: 'yp_product_unfavorite',\n AddToWishlist: 'yp_product_favorite',\n RemoveFromWishlist: 'yp_product_unfavorite',\n ViewBrand: 'yp_brand_view',\n FavoriteBrand: 'yp_brand_favorite',\n UnfavoriteBrand: 'yp_brand_unfavorite',\n} as const;\n\nexport type EventTypeValue = (typeof EventType)[keyof typeof EventType];\n\nexport const GaEventType: Record<string, string> = {\n [EventType.ViewProduct]: 'view_item',\n [EventType.SelectItem]: 'select_item',\n [EventType.AddToCart]: 'add_to_cart',\n [EventType.RemoveFromCart]: 'remove_from_cart',\n [EventType.BeginCheckout]: 'begin_checkout',\n [EventType.Purchase]: 'purchase',\n [EventType.FavoriteProduct]: 'add_to_wishlist',\n [EventType.UnfavoriteProduct]: 'remove_from_wishlist',\n};\n\nexport const GaEventTypeReverse: Record<string, string> = {\n view_item: EventType.ViewProduct,\n select_item: EventType.SelectItem,\n add_to_cart: EventType.AddToCart,\n remove_from_cart: EventType.RemoveFromCart,\n begin_checkout: EventType.BeginCheckout,\n purchase: EventType.Purchase,\n add_to_wishlist: EventType.FavoriteProduct,\n remove_from_wishlist: EventType.UnfavoriteProduct,\n};\n\nexport const ItemListId = {\n SEARCH_RESULTS: 'search-results',\n PRODUCT_LIST: 'product-list',\n YOU_MAY_ALSO_LIKE: 'you-may-also-like',\n COMPLETE_THE_LOOK: 'complete-the-look',\n COLLABORATIVE_FILTERING: 'collaborative-filtering',\n MORE_FROM_BRAND: 'more-from-brand',\n STYLE_WITH: 'style-with',\n SHOPPING_CART: 'shopping-cart',\n ITEM_FOR_YOU: 'item-for-you',\n BRAND_FOR_YOU: 'brand-for-you',\n} as const;\n\nexport type ItemListIdValue = (typeof ItemListId)[keyof typeof ItemListId];\n\nconst LIST_ID_ALIASES: Record<string, string> = {\n Search: ItemListId.SEARCH_RESULTS,\n 'search-results': ItemListId.SEARCH_RESULTS,\n PLP: ItemListId.PRODUCT_LIST,\n 'product-list': ItemListId.PRODUCT_LIST,\n YMAL: ItemListId.YOU_MAY_ALSO_LIKE,\n 'you-may-also-like': ItemListId.YOU_MAY_ALSO_LIKE,\n CTL: ItemListId.COMPLETE_THE_LOOK,\n 'complete-the-look': ItemListId.COMPLETE_THE_LOOK,\n CF: ItemListId.COLLABORATIVE_FILTERING,\n 'collaborative-filtering': ItemListId.COLLABORATIVE_FILTERING,\n 'frequently-bought-together': ItemListId.COLLABORATIVE_FILTERING,\n Brand: ItemListId.MORE_FROM_BRAND,\n 'more-from-brand': ItemListId.MORE_FROM_BRAND,\n STW: ItemListId.STYLE_WITH,\n 'style-with': ItemListId.STYLE_WITH,\n CART: ItemListId.SHOPPING_CART,\n 'shopping-cart': ItemListId.SHOPPING_CART,\n 'item-for-you': ItemListId.ITEM_FOR_YOU,\n 'brand-for-you': ItemListId.BRAND_FOR_YOU,\n};\n\nexport function normalizeItemListId(input: string | undefined | null): string | undefined | null {\n if (!input) return input;\n const alias = LIST_ID_ALIASES[input];\n if (alias) return alias;\n const canonical = Object.values(ItemListId) as string[];\n if (canonical.includes(input)) return input;\n return input;\n}\n\nexport const API_EVENTS: string[] = [\n EventType.ViewProduct,\n EventType.AddToCart,\n EventType.RemoveFromCart,\n EventType.BeginCheckout,\n EventType.Purchase,\n EventType.FavoriteProduct,\n EventType.UnfavoriteProduct,\n EventType.ViewBrand,\n EventType.FavoriteBrand,\n EventType.UnfavoriteBrand,\n];\n","import AsyncStorage from '@react-native-async-storage/async-storage';\n\nexport const StorageKeys = {\n CID: 'yp_cid',\n SESSION: 'yp_session',\n USER_ID: 'yp_user_id',\n USER_PROPS: 'yp_user_props',\n ATTRIBUTION: 'yp_attribution',\n PENDING_EVENTS: 'yp_pending_events',\n} as const;\n\nexport const Storage = {\n async getItem(key: string): Promise<string | null> {\n try {\n return await AsyncStorage.getItem(key);\n } catch {\n return null;\n }\n },\n async setItem(key: string, value: string): Promise<void> {\n try {\n await AsyncStorage.setItem(key, value);\n } catch {\n // ignore\n }\n },\n async removeItem(key: string): Promise<void> {\n try {\n await AsyncStorage.removeItem(key);\n } catch {\n // ignore\n }\n },\n async getJSON<T>(key: string, fallback: T): Promise<T> {\n const raw = await Storage.getItem(key);\n if (!raw) return fallback;\n try {\n return JSON.parse(raw) as T;\n } catch {\n return fallback;\n }\n },\n async setJSON(key: string, value: unknown): Promise<void> {\n try {\n await Storage.setItem(key, JSON.stringify(value));\n } catch {\n // ignore\n }\n },\n};\n","import { Storage, StorageKeys } from './storage';\n\nexport function generateId(): string {\n return Date.now().toString(36) + Math.random().toString(36).substring(2);\n}\n\nexport function hashCode(str: string): number {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n hash = (hash << 5) - hash + str.charCodeAt(i);\n hash |= 0;\n }\n return hash;\n}\n\nexport function numericSessionId(sessionId: string | null | undefined): number {\n if (!sessionId) return Math.floor(Date.now() / 1000);\n return Math.abs(hashCode(sessionId)) || Math.floor(Date.now() / 1000);\n}\n\nexport interface Identity {\n cid: string;\n sessionId: string;\n userId: string | null;\n userProperties: Record<string, unknown>;\n}\n\nexport async function loadIdentity(): Promise<Identity> {\n const [cidStored, sessionStored, userIdStored, userPropsStored] = await Promise.all([\n Storage.getItem(StorageKeys.CID),\n Storage.getItem(StorageKeys.SESSION),\n Storage.getItem(StorageKeys.USER_ID),\n Storage.getItem(StorageKeys.USER_PROPS),\n ]);\n\n let cid = cidStored;\n if (!cid) {\n cid = generateId();\n await Storage.setItem(StorageKeys.CID, cid);\n }\n\n let sessionId = sessionStored;\n if (!sessionId) {\n sessionId = generateId();\n await Storage.setItem(StorageKeys.SESSION, sessionId);\n }\n\n let userProperties: Record<string, unknown> = {};\n if (userPropsStored) {\n try {\n userProperties = JSON.parse(userPropsStored) as Record<string, unknown>;\n } catch {\n userProperties = {};\n }\n }\n\n return { cid, sessionId, userId: userIdStored, userProperties };\n}\n\nexport async function saveCid(cid: string): Promise<void> {\n await Storage.setItem(StorageKeys.CID, cid);\n}\n\nexport async function saveSession(sessionId: string): Promise<void> {\n await Storage.setItem(StorageKeys.SESSION, sessionId);\n}\n\nexport async function saveUser(\n userId: string,\n userProperties: Record<string, unknown>,\n cacheUserId: boolean\n): Promise<void> {\n if (cacheUserId) {\n await Storage.setItem(StorageKeys.USER_ID, userId);\n }\n await Storage.setJSON(StorageKeys.USER_PROPS, userProperties);\n}\n\nexport async function clearUser(): Promise<void> {\n await Storage.removeItem(StorageKeys.USER_ID);\n await Storage.removeItem(StorageKeys.USER_PROPS);\n}\n","import { Storage, StorageKeys } from './storage';\nimport { EventType, GaEventTypeReverse } from './constants';\nimport type { TrackProperties } from './types';\n\nconst EXPIRY_MS = 30 * 60 * 1000;\n\ntype AttributionRecord = { source: string; ts: number };\ntype AttributionStore = Record<string, AttributionRecord>;\n\nfunction normalizeId(rawId: unknown, idPrefix?: string): string | null {\n if (!rawId) return null;\n const idStr = String(rawId);\n if (idPrefix && idStr.startsWith(idPrefix)) {\n return idStr.slice(idPrefix.length);\n }\n const match = idStr.match(/^[a-zA-Z]+-(.+)$/);\n return match ? match[1] : idStr;\n}\n\nasync function loadStore(): Promise<AttributionStore> {\n return Storage.getJSON<AttributionStore>(StorageKeys.ATTRIBUTION, {});\n}\n\nasync function saveStore(store: AttributionStore): Promise<void> {\n await Storage.setJSON(StorageKeys.ATTRIBUTION, store);\n}\n\nfunction pruneExpired(store: AttributionStore): AttributionStore {\n const now = Date.now();\n const next: AttributionStore = {};\n for (const [k, v] of Object.entries(store)) {\n if (now - v.ts <= EXPIRY_MS) next[k] = v;\n }\n return next;\n}\n\nexport async function handleAttribution(\n eventType: string,\n props: TrackProperties,\n idPrefix?: string\n): Promise<void> {\n const normalizedEventType = GaEventTypeReverse[eventType] || eventType;\n\n if (normalizedEventType === EventType.SelectItem) {\n const itemListId = props.item_list_id;\n const rawId = props.id ?? props.items?.[0]?.item_id;\n const productId = normalizeId(rawId, idPrefix);\n if (itemListId && productId) {\n let store = await loadStore();\n store = pruneExpired(store);\n store[productId] = { source: itemListId, ts: Date.now() };\n await saveStore(store);\n }\n return;\n }\n\n if (normalizedEventType === EventType.ViewProduct) {\n const rawId = props.id ?? props.items?.[0]?.item_id;\n const productId = normalizeId(rawId, idPrefix);\n if (!productId) return;\n const store = await loadStore();\n const entry = store[productId];\n if (entry && Date.now() - entry.ts <= EXPIRY_MS) {\n props.item_list_id = entry.source;\n if (Array.isArray(props.items)) {\n props.items = props.items.map((item) => ({ ...item, item_list_id: entry.source }));\n }\n }\n return;\n }\n\n if (normalizedEventType === EventType.AddToCart) {\n if (!Array.isArray(props.items)) return;\n const store = await loadStore();\n props.items = props.items.map((item) => {\n const productId = normalizeId(item.item_id, idPrefix);\n const entry = productId ? store[productId] : null;\n if (entry && Date.now() - entry.ts <= EXPIRY_MS) {\n return { ...item, item_list_id: entry.source };\n }\n return item;\n });\n const firstMatch = props.items.find((item) => item.item_list_id);\n if (firstMatch?.item_list_id) {\n props.item_list_id = firstMatch.item_list_id;\n }\n }\n}\n\nexport async function getAttribution(productId: string): Promise<string | null> {\n const store = await loadStore();\n const entry = store[String(productId)];\n if (entry && Date.now() - entry.ts < EXPIRY_MS) return entry.source;\n return null;\n}\n","import { GaEventType } from './constants';\nimport type { TrackProperties } from './types';\n\nfunction toSnakeCase(str: string): string {\n return str.replace(/-/g, '_');\n}\n\nexport interface GaSendOptions {\n gaProxyUrl: string;\n clientId: string;\n sessionId: string;\n numericSessionId: number;\n userId?: string | null;\n debug?: boolean;\n}\n\nexport async function sendToGA(\n eventType: string,\n props: TrackProperties,\n options: GaSendOptions\n): Promise<void> {\n const gaEvent = GaEventType[eventType] || toSnakeCase(eventType);\n const {\n items,\n currency,\n value,\n transaction_id,\n tax,\n shipping,\n coupon,\n ...rest\n } = props;\n\n const params: Record<string, unknown> = {\n session_id: options.numericSessionId,\n engagement_time_msec: 1,\n session_engaged: '1',\n };\n\n if (currency) params.currency = currency;\n if (value !== undefined) params.value = value;\n if (transaction_id) params.transaction_id = transaction_id;\n if (tax !== undefined) params.tax = tax;\n if (shipping !== undefined) params.shipping = shipping;\n if (coupon) params.coupon = coupon;\n if (items) params.items = items;\n\n const passthroughKeys = [\n 'item_list_id',\n 'data_provider',\n 'event_source',\n 'id',\n 'search_term',\n 'total',\n 'total_text',\n 'total_vector',\n 'page_location',\n 'page_title',\n 'page_referrer',\n 'language',\n 'test_marker',\n 'yp_platform',\n 'yp_platform_version',\n 'yp_user_agent',\n ];\n for (const key of passthroughKeys) {\n if (rest[key] !== undefined) params[key] = rest[key];\n }\n\n const body: Record<string, unknown> = {\n client_id: options.clientId || options.sessionId,\n timestamp_micros: Date.now() * 1000,\n events: [{ name: gaEvent, params }],\n };\n\n if (options.userId) body.user_id = options.userId;\n\n const sep = options.gaProxyUrl.includes('?') ? '&' : '?';\n const url = options.debug\n ? `${options.gaProxyUrl}${sep}debug=1`\n : options.gaProxyUrl;\n\n try {\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n if (options.debug) {\n // eslint-disable-next-line no-console\n console.log(`[YesPlz Analytics] GA MP → ${gaEvent} (status ${res.status})`);\n }\n } catch (e) {\n if (options.debug) {\n // eslint-disable-next-line no-console\n console.log(`[YesPlz Analytics] GA MP error: ${(e as Error).message}`);\n }\n }\n}\n","import { Storage, StorageKeys } from './storage';\nimport type { ApiEvent } from './types';\n\nexport interface BeaconOptions {\n apiEndpoint: string;\n apiToken?: string | null;\n defaultParams?: Record<string, unknown>;\n idPrefix?: string;\n debounceMs?: number;\n debug?: boolean;\n}\n\nexport class Beacon {\n private queue: ApiEvent[] = [];\n private isSending = false;\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(private options: BeaconOptions) {}\n\n enqueue(event: ApiEvent): void {\n this.queue.push(event);\n this.scheduleSend();\n }\n\n enqueueAll(events: ApiEvent[]): void {\n this.queue.push(...events);\n this.scheduleSend();\n }\n\n private scheduleSend(): void {\n if (this.debounceTimer) clearTimeout(this.debounceTimer);\n this.debounceTimer = setTimeout(() => {\n void this.send();\n }, this.options.debounceMs ?? 1000);\n }\n\n async send(retryCount = 0): Promise<void> {\n if (this.queue.length === 0) return;\n if (!this.options.apiEndpoint) return;\n if (this.isSending) return;\n\n this.isSending = true;\n const eventsToSend = this.queue.splice(0, this.queue.length);\n\n const events = eventsToSend.map((event) => {\n const merged: Record<string, unknown> = {\n ...event,\n ...(this.options.defaultParams ?? {}),\n };\n const rawId = (event.extra_data as Record<string, unknown>).id;\n if (rawId && this.options.idPrefix) {\n merged.extra_data = {\n ...event.extra_data,\n id: `${this.options.idPrefix}${rawId}`,\n };\n }\n return merged;\n });\n\n try {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (this.options.apiToken) headers.Authorization = `Token ${this.options.apiToken}`;\n\n const res = await fetch(this.options.apiEndpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify(events),\n });\n\n if (res.status > 299) {\n throw new Error(`Failed to send events (status ${res.status})`);\n }\n\n if (this.options.debug) {\n // eslint-disable-next-line no-console\n console.log(`[YesPlz Analytics] Sync: ${events.length} events sent`);\n }\n await Storage.removeItem(StorageKeys.PENDING_EVENTS);\n } catch (e) {\n if (this.options.debug) {\n // eslint-disable-next-line no-console\n console.log(`[YesPlz Analytics] Sync failed: ${(e as Error).message}`);\n }\n this.queue.unshift(...eventsToSend);\n this.isSending = false;\n if (retryCount < 1) {\n setTimeout(() => void this.send(retryCount + 1), 2000);\n }\n return;\n }\n\n this.isSending = false;\n if (this.queue.length > 0) this.scheduleSend();\n }\n\n async flush(): Promise<void> {\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n await this.send();\n }\n\n async savePending(): Promise<void> {\n if (this.queue.length === 0) return;\n const toSave = this.queue.slice(-100);\n await Storage.setJSON(StorageKeys.PENDING_EVENTS, toSave);\n this.queue = [];\n }\n\n async restorePending(): Promise<void> {\n const pending = await Storage.getJSON<ApiEvent[]>(StorageKeys.PENDING_EVENTS, []);\n if (pending.length > 0) {\n this.queue.unshift(...pending);\n await Storage.removeItem(StorageKeys.PENDING_EVENTS);\n this.scheduleSend();\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/analytics.ts","../src/constants.ts","../src/storage.ts","../src/ids.ts","../src/attribution.ts","../src/ga.ts","../src/beacon.ts"],"sourcesContent":["import { Platform, AppState, type AppStateStatus } from 'react-native';\nimport {\n API_EVENTS,\n EventType,\n GaEventType,\n GaEventTypeReverse,\n normalizeItemListId,\n VERSION,\n} from './constants';\nimport { Storage, StorageKeys } from './storage';\nimport {\n generateId,\n loadIdentity,\n numericSessionId,\n saveSession,\n saveUser,\n clearUser as clearUserStorage,\n} from './ids';\nimport { handleAttribution } from './attribution';\nimport { sendToGA } from './ga';\nimport { Beacon } from './beacon';\nimport type {\n AnalyticsConfig,\n ApiEvent,\n EventMetadata,\n TrackProperties,\n} from './types';\n\nconst DEFAULT_DEBOUNCE_MS = 1000;\nconst DEFAULT_API_BASE_URL = 'https://api.yesplz.ai';\nconst DEFAULT_GA_PROXY_BASE_URL = 'https://ypsh-admin.yesplz.ai/api/mp/collect';\n\nfunction buildUserAgent(): string {\n const os = Platform.OS;\n const version = Platform.Version;\n return `YesPlzSDK-RN/${VERSION} (${os}; ${String(version)})`;\n}\n\nexport class Analytics {\n private config: Required<\n Pick<AnalyticsConfig, 'debug' | 'debounceMs' | 'cacheUserId' | 'idPrefix'>\n > &\n Omit<AnalyticsConfig, 'debug' | 'debounceMs' | 'cacheUserId' | 'idPrefix'> & {\n appId?: string;\n gaProxyUrl?: string;\n } = {\n debug: false,\n debounceMs: DEFAULT_DEBOUNCE_MS,\n cacheUserId: true,\n idPrefix: '',\n };\n\n private cid: string | null = null;\n private sessionId: string | null = null;\n private userId: string | null = null;\n private userProperties: Record<string, unknown> = {};\n private isInitialized = false;\n private initPromise: Promise<void> | null = null;\n private beacon: Beacon | null = null;\n private pendingTracks: { eventType: string; properties: TrackProperties }[] = [];\n private appStateSubscription: { remove(): void } | null = null;\n\n init(appId: string, config: AnalyticsConfig = {}): Analytics {\n if (this.isInitialized || this.initPromise) return this;\n this.initPromise = this.initInternal(appId, config);\n void this.initPromise;\n return this;\n }\n\n ready(): Promise<void> {\n return this.initPromise ?? Promise.resolve();\n }\n\n private async initInternal(appId: string, config: AnalyticsConfig): Promise<void> {\n const normalizedAppId = String(appId).trim();\n if (!normalizedAppId) {\n throw new Error('[YesPlz Analytics] appId must be a non-empty string');\n }\n\n const apiBaseUrl = (config.apiBaseUrl || DEFAULT_API_BASE_URL).replace(/\\/$/, '');\n const apiEndpoint =\n config.apiEndpoint ||\n `${apiBaseUrl}/api/v1/retailer/${encodeURIComponent(normalizedAppId)}/interactions/`;\n const gaProxyBaseUrl = config.gaProxyBaseUrl || DEFAULT_GA_PROXY_BASE_URL;\n const gaProxySep = gaProxyBaseUrl.includes('?') ? '&' : '?';\n const gaProxyUrl = `${gaProxyBaseUrl}${gaProxySep}shop=${encodeURIComponent(normalizedAppId)}`;\n\n const mergedDefaultParams: Record<string, unknown> = {\n ...(config.defaultParams || {}),\n };\n if (config.testMarker) {\n mergedDefaultParams.test_marker = config.testMarker;\n }\n\n this.config = {\n ...this.config,\n appId: normalizedAppId,\n apiEndpoint,\n apiBaseUrl,\n apiToken: config.apiToken ?? null,\n gaProxyBaseUrl,\n gaProxyUrl,\n idPrefix: config.idPrefix || '',\n defaultParams: mergedDefaultParams,\n testMarker: config.testMarker,\n debug: config.debug ?? false,\n cacheUserId: config.cacheUserId ?? true,\n debounceMs: config.debounceMs || DEFAULT_DEBOUNCE_MS,\n };\n\n const identity = await loadIdentity();\n this.cid = identity.cid;\n this.sessionId = identity.sessionId;\n this.userId = identity.userId;\n this.userProperties = identity.userProperties;\n\n if (config.userId) {\n await this.setUserInternal(config.userId, config.userProperties || {});\n }\n\n if (apiEndpoint) {\n this.beacon = new Beacon({\n apiEndpoint,\n apiToken: this.config.apiToken,\n defaultParams: this.config.defaultParams,\n idPrefix: this.config.idPrefix,\n debounceMs: this.config.debounceMs,\n debug: this.config.debug,\n });\n await this.beacon.restorePending();\n }\n\n this.appStateSubscription = AppState.addEventListener(\n 'change',\n (state: AppStateStatus) => {\n if (state === 'background' || state === 'inactive') {\n void this.beacon?.savePending();\n }\n }\n );\n\n this.isInitialized = true;\n this.log('Initialized');\n\n const queued = this.pendingTracks.splice(0, this.pendingTracks.length);\n for (const item of queued) {\n void this.dispatchTrack(item.eventType, item.properties);\n }\n }\n\n async setUser(\n userId: string | null,\n userProperties: Record<string, unknown> = {}\n ): Promise<Analytics> {\n await this.ready();\n if (userId === null) {\n this.userId = null;\n this.userProperties = {};\n await clearUserStorage();\n this.log('User cleared');\n return this;\n }\n await this.setUserInternal(userId, userProperties);\n return this;\n }\n\n private async setUserInternal(\n userId: string,\n userProperties: Record<string, unknown>\n ): Promise<void> {\n const id = String(userId);\n if (id.length === 0) {\n // eslint-disable-next-line no-console\n console.error('[YesPlz Analytics] User ID must be a non-empty value');\n return;\n }\n this.userId = id;\n this.userProperties = JSON.parse(JSON.stringify(userProperties));\n await saveUser(this.userId, this.userProperties, this.config.cacheUserId);\n this.log(`User set: ${id}`);\n }\n\n getUser(): { userId: string; userProperties: Record<string, unknown> } | null {\n if (!this.userId) return null;\n return { userId: this.userId, userProperties: this.userProperties };\n }\n\n getSessionId(): string | null {\n return this.sessionId;\n }\n\n getClientId(): string | null {\n return this.cid;\n }\n\n track(eventType: string, properties: TrackProperties = {}): Analytics {\n if (typeof eventType !== 'string' || eventType.length === 0) {\n // eslint-disable-next-line no-console\n console.error('[YesPlz Analytics] Event type must be a non-empty string');\n return this;\n }\n\n if (!this.isInitialized) {\n this.pendingTracks.push({\n eventType,\n properties: JSON.parse(JSON.stringify(properties)),\n });\n return this;\n }\n\n void this.dispatchTrack(eventType, properties);\n return this;\n }\n\n private async dispatchTrack(\n eventType: string,\n properties: TrackProperties\n ): Promise<void> {\n const props: TrackProperties = JSON.parse(JSON.stringify(properties));\n\n await handleAttribution(eventType, props, this.config.idPrefix);\n\n if (eventType === EventType.Purchase && !props.transaction_id) {\n props.transaction_id = generateId();\n }\n\n if (props.id && !Array.isArray(props.items)) {\n props.items = [{ item_id: props.id, ...(props as Record<string, unknown>) }];\n }\n\n if (props.item_list_id) {\n props.item_list_id = normalizeItemListId(props.item_list_id) || undefined;\n }\n if (Array.isArray(props.items)) {\n props.items = props.items.map((item) =>\n item.item_list_id ? { ...item, item_list_id: normalizeItemListId(item.item_list_id) || undefined } : item\n );\n }\n\n const metadata = this.collectMetadata();\n Object.assign(props, metadata);\n props.data_provider = 'yesplz';\n if (this.config.testMarker) {\n props.test_marker = this.config.testMarker;\n }\n\n await this.sendGA(eventType, props);\n\n const apiEventType = GaEventTypeReverse[eventType] || eventType;\n if (API_EVENTS.includes(apiEventType)) {\n this.queueApi(apiEventType, props, metadata);\n }\n }\n\n private async sendGA(eventType: string, props: TrackProperties): Promise<void> {\n if (!this.config.gaProxyUrl) return;\n if (!this.cid || !this.sessionId) return;\n\n const gaEventName = GaEventType[eventType] ?? eventType;\n await sendToGA(eventType, props, {\n gaProxyUrl: this.config.gaProxyUrl,\n clientId: this.cid,\n sessionId: this.sessionId,\n numericSessionId: numericSessionId(this.sessionId),\n userId: this.userId,\n debug: this.config.debug,\n });\n this.log(`Track: ${gaEventName}`, props.items?.length ? { items: props.items.length } : undefined);\n }\n\n private queueApi(\n eventType: string,\n props: TrackProperties,\n metadata: EventMetadata\n ): void {\n if (!this.beacon) return;\n const items = props.items && props.items.length > 0 ? props.items : [props];\n const fallbackUrl = `app://${this.config.appId ?? 'yesplz'}/`;\n const url =\n typeof props.page_location === 'string' && props.page_location.length > 0\n ? props.page_location\n : fallbackUrl;\n const referrerUrl =\n typeof props.page_referrer === 'string' && props.page_referrer.length > 0\n ? props.page_referrer\n : null;\n\n const events: ApiEvent[] = items.map((item) => {\n const merged: Record<string, unknown> = {\n ...(props as Record<string, unknown>),\n ...(item as Record<string, unknown>),\n ...metadata,\n };\n const itemId = (item as { item_id?: string }).item_id;\n if (itemId) merged.id = itemId;\n merged.identifier_type = eventType.startsWith('yp_brand_')\n ? 'brand_name'\n : 'product_id';\n\n const event: ApiEvent = {\n event_type: eventType,\n url,\n referrer_url: referrerUrl,\n user_id: this.userId,\n session_id: this.sessionId,\n extra_data: merged,\n };\n if (Object.keys(this.userProperties).length > 0) {\n event.extra_user_data = this.userProperties;\n }\n return event;\n });\n\n this.beacon.enqueueAll(events);\n }\n\n private collectMetadata(): EventMetadata {\n const metadata: EventMetadata = {\n yp_client_time: Date.now(),\n yp_platform: Platform.OS,\n yp_platform_version: String(Platform.Version),\n yp_user_agent: buildUserAgent(),\n yp_timezone_offset: new Date().getTimezoneOffset(),\n };\n try {\n metadata.yp_timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch {\n // ignore\n }\n if (this.cid) metadata.google_client_id = this.cid;\n return metadata;\n }\n\n async flush(): Promise<Analytics> {\n await this.ready();\n await this.beacon?.flush();\n return this;\n }\n\n async reset(): Promise<Analytics> {\n await this.ready();\n this.userId = null;\n this.userProperties = {};\n await clearUserStorage();\n await Storage.removeItem(StorageKeys.PENDING_EVENTS);\n await Storage.removeItem(StorageKeys.ATTRIBUTION);\n const newSession = generateId();\n this.sessionId = newSession;\n await saveSession(newSession);\n this.log('Reset');\n return this;\n }\n\n teardown(): void {\n this.appStateSubscription?.remove();\n this.appStateSubscription = null;\n }\n\n private log(message: string, data?: unknown): void {\n if (this.config.debug) {\n // eslint-disable-next-line no-console\n console.log(`[YesPlz Analytics] ${message}`, data ?? '');\n }\n }\n}\n\nconst globalRef = (globalThis as unknown as { __yesplz_analytics_rn__?: Analytics });\nexport const analytics: Analytics =\n globalRef.__yesplz_analytics_rn__ ||\n (globalRef.__yesplz_analytics_rn__ = new Analytics());\n","export const VERSION = '0.1.0-rn';\n\nexport const EventType = {\n ViewItemList: 'view_item_list',\n ViewItem: 'yp_product_view',\n ViewProduct: 'yp_product_view',\n SelectItem: 'yp_product_select',\n SelectProduct: 'yp_product_select',\n AddToCart: 'yp_product_cart',\n RemoveFromCart: 'yp_product_remove_from_cart',\n BeginCheckout: 'yp_begin_checkout',\n Purchase: 'yp_product_purchase',\n FavoriteProduct: 'yp_product_favorite',\n UnfavoriteProduct: 'yp_product_unfavorite',\n AddToWishlist: 'yp_product_favorite',\n RemoveFromWishlist: 'yp_product_unfavorite',\n ViewBrand: 'yp_brand_view',\n FavoriteBrand: 'yp_brand_favorite',\n UnfavoriteBrand: 'yp_brand_unfavorite',\n} as const;\n\nexport type EventTypeValue = (typeof EventType)[keyof typeof EventType];\n\nexport const GaEventType: Record<string, string> = {\n [EventType.ViewProduct]: 'view_item',\n [EventType.SelectItem]: 'select_item',\n [EventType.AddToCart]: 'add_to_cart',\n [EventType.RemoveFromCart]: 'remove_from_cart',\n [EventType.BeginCheckout]: 'begin_checkout',\n [EventType.Purchase]: 'purchase',\n [EventType.FavoriteProduct]: 'add_to_wishlist',\n [EventType.UnfavoriteProduct]: 'remove_from_wishlist',\n};\n\nexport const GaEventTypeReverse: Record<string, string> = {\n view_item: EventType.ViewProduct,\n select_item: EventType.SelectItem,\n add_to_cart: EventType.AddToCart,\n remove_from_cart: EventType.RemoveFromCart,\n begin_checkout: EventType.BeginCheckout,\n purchase: EventType.Purchase,\n add_to_wishlist: EventType.FavoriteProduct,\n remove_from_wishlist: EventType.UnfavoriteProduct,\n};\n\nexport const ItemListId = {\n SEARCH_RESULTS: 'search_results',\n PRODUCT_LIST: 'category',\n YOU_MAY_ALSO_LIKE: 'rec_YMAL',\n COMPLETE_THE_LOOK: 'rec_CTL',\n COLLABORATIVE_FILTERING: 'rec_CF',\n MORE_FROM_BRAND: 'rec_Brand',\n STYLE_WITH: 'STW',\n SHOPPING_CART: 'rec_CART',\n ITEM_FOR_YOU: 'item-for-you',\n BRAND_FOR_YOU: 'brand-for-you',\n} as const;\n\nexport type ItemListIdValue = (typeof ItemListId)[keyof typeof ItemListId];\n\nconst LIST_ID_ALIASES: Record<string, string> = {\n Search: ItemListId.SEARCH_RESULTS,\n search_results: ItemListId.SEARCH_RESULTS,\n 'search-results': ItemListId.SEARCH_RESULTS,\n PLP: ItemListId.PRODUCT_LIST,\n category: ItemListId.PRODUCT_LIST,\n 'product-list': ItemListId.PRODUCT_LIST,\n YMAL: ItemListId.YOU_MAY_ALSO_LIKE,\n rec_YMAL: ItemListId.YOU_MAY_ALSO_LIKE,\n 'you-may-also-like': ItemListId.YOU_MAY_ALSO_LIKE,\n CTL: ItemListId.COMPLETE_THE_LOOK,\n rec_CTL: ItemListId.COMPLETE_THE_LOOK,\n 'complete-the-look': ItemListId.COMPLETE_THE_LOOK,\n CF: ItemListId.COLLABORATIVE_FILTERING,\n rec_CF: ItemListId.COLLABORATIVE_FILTERING,\n 'collaborative-filtering': ItemListId.COLLABORATIVE_FILTERING,\n 'frequently-bought-together': ItemListId.COLLABORATIVE_FILTERING,\n Brand: ItemListId.MORE_FROM_BRAND,\n rec_Brand: ItemListId.MORE_FROM_BRAND,\n 'more-from-brand': ItemListId.MORE_FROM_BRAND,\n STW: ItemListId.STYLE_WITH,\n 'style-with': ItemListId.STYLE_WITH,\n CART: ItemListId.SHOPPING_CART,\n rec_CART: ItemListId.SHOPPING_CART,\n 'shopping-cart': ItemListId.SHOPPING_CART,\n 'item-for-you': ItemListId.ITEM_FOR_YOU,\n 'brand-for-you': ItemListId.BRAND_FOR_YOU,\n};\n\nexport function normalizeItemListId(input: string | undefined | null): string | undefined | null {\n if (!input) return input;\n const alias = LIST_ID_ALIASES[input];\n if (alias) return alias;\n const canonical = Object.values(ItemListId) as string[];\n if (canonical.includes(input)) return input;\n return input;\n}\n\nexport const API_EVENTS: string[] = [\n EventType.ViewProduct,\n EventType.AddToCart,\n EventType.RemoveFromCart,\n EventType.BeginCheckout,\n EventType.Purchase,\n EventType.FavoriteProduct,\n EventType.UnfavoriteProduct,\n EventType.ViewBrand,\n EventType.FavoriteBrand,\n EventType.UnfavoriteBrand,\n];\n","import AsyncStorage from '@react-native-async-storage/async-storage';\n\nexport const StorageKeys = {\n CID: 'yp_cid',\n SESSION: 'yp_session',\n USER_ID: 'yp_user_id',\n USER_PROPS: 'yp_user_props',\n ATTRIBUTION: 'yp_attribution',\n PENDING_EVENTS: 'yp_pending_events',\n} as const;\n\nexport const Storage = {\n async getItem(key: string): Promise<string | null> {\n try {\n return await AsyncStorage.getItem(key);\n } catch {\n return null;\n }\n },\n async setItem(key: string, value: string): Promise<void> {\n try {\n await AsyncStorage.setItem(key, value);\n } catch {\n // ignore\n }\n },\n async removeItem(key: string): Promise<void> {\n try {\n await AsyncStorage.removeItem(key);\n } catch {\n // ignore\n }\n },\n async getJSON<T>(key: string, fallback: T): Promise<T> {\n const raw = await Storage.getItem(key);\n if (!raw) return fallback;\n try {\n return JSON.parse(raw) as T;\n } catch {\n return fallback;\n }\n },\n async setJSON(key: string, value: unknown): Promise<void> {\n try {\n await Storage.setItem(key, JSON.stringify(value));\n } catch {\n // ignore\n }\n },\n};\n","import { Storage, StorageKeys } from './storage';\n\nexport function generateId(): string {\n return Date.now().toString(36) + Math.random().toString(36).substring(2);\n}\n\nexport function hashCode(str: string): number {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n hash = (hash << 5) - hash + str.charCodeAt(i);\n hash |= 0;\n }\n return hash;\n}\n\nexport function numericSessionId(sessionId: string | null | undefined): number {\n if (!sessionId) return Math.floor(Date.now() / 1000);\n return Math.abs(hashCode(sessionId)) || Math.floor(Date.now() / 1000);\n}\n\nexport interface Identity {\n cid: string;\n sessionId: string;\n userId: string | null;\n userProperties: Record<string, unknown>;\n}\n\nexport async function loadIdentity(): Promise<Identity> {\n const [cidStored, sessionStored, userIdStored, userPropsStored] = await Promise.all([\n Storage.getItem(StorageKeys.CID),\n Storage.getItem(StorageKeys.SESSION),\n Storage.getItem(StorageKeys.USER_ID),\n Storage.getItem(StorageKeys.USER_PROPS),\n ]);\n\n let cid = cidStored;\n if (!cid) {\n cid = generateId();\n await Storage.setItem(StorageKeys.CID, cid);\n }\n\n let sessionId = sessionStored;\n if (!sessionId) {\n sessionId = generateId();\n await Storage.setItem(StorageKeys.SESSION, sessionId);\n }\n\n let userProperties: Record<string, unknown> = {};\n if (userPropsStored) {\n try {\n userProperties = JSON.parse(userPropsStored) as Record<string, unknown>;\n } catch {\n userProperties = {};\n }\n }\n\n return { cid, sessionId, userId: userIdStored, userProperties };\n}\n\nexport async function saveCid(cid: string): Promise<void> {\n await Storage.setItem(StorageKeys.CID, cid);\n}\n\nexport async function saveSession(sessionId: string): Promise<void> {\n await Storage.setItem(StorageKeys.SESSION, sessionId);\n}\n\nexport async function saveUser(\n userId: string,\n userProperties: Record<string, unknown>,\n cacheUserId: boolean\n): Promise<void> {\n if (cacheUserId) {\n await Storage.setItem(StorageKeys.USER_ID, userId);\n }\n await Storage.setJSON(StorageKeys.USER_PROPS, userProperties);\n}\n\nexport async function clearUser(): Promise<void> {\n await Storage.removeItem(StorageKeys.USER_ID);\n await Storage.removeItem(StorageKeys.USER_PROPS);\n}\n","import { Storage, StorageKeys } from './storage';\nimport { EventType, GaEventTypeReverse } from './constants';\nimport type { TrackProperties } from './types';\n\nconst EXPIRY_MS = 30 * 60 * 1000;\n\ntype AttributionRecord = { source: string; ts: number };\ntype AttributionStore = Record<string, AttributionRecord>;\n\nfunction normalizeId(rawId: unknown, idPrefix?: string): string | null {\n if (!rawId) return null;\n const idStr = String(rawId);\n if (idPrefix && idStr.startsWith(idPrefix)) {\n return idStr.slice(idPrefix.length);\n }\n const match = idStr.match(/^[a-zA-Z]+-(.+)$/);\n return match ? match[1] : idStr;\n}\n\nasync function loadStore(): Promise<AttributionStore> {\n return Storage.getJSON<AttributionStore>(StorageKeys.ATTRIBUTION, {});\n}\n\nasync function saveStore(store: AttributionStore): Promise<void> {\n await Storage.setJSON(StorageKeys.ATTRIBUTION, store);\n}\n\nfunction pruneExpired(store: AttributionStore): AttributionStore {\n const now = Date.now();\n const next: AttributionStore = {};\n for (const [k, v] of Object.entries(store)) {\n if (now - v.ts <= EXPIRY_MS) next[k] = v;\n }\n return next;\n}\n\nexport async function handleAttribution(\n eventType: string,\n props: TrackProperties,\n idPrefix?: string\n): Promise<void> {\n const normalizedEventType = GaEventTypeReverse[eventType] || eventType;\n\n if (normalizedEventType === EventType.SelectItem) {\n const itemListId = props.item_list_id;\n const rawId = props.id ?? props.items?.[0]?.item_id;\n const productId = normalizeId(rawId, idPrefix);\n if (itemListId && productId) {\n let store = await loadStore();\n store = pruneExpired(store);\n store[productId] = { source: itemListId, ts: Date.now() };\n await saveStore(store);\n }\n return;\n }\n\n if (normalizedEventType === EventType.ViewProduct) {\n const rawId = props.id ?? props.items?.[0]?.item_id;\n const productId = normalizeId(rawId, idPrefix);\n if (!productId) return;\n const store = await loadStore();\n const entry = store[productId];\n if (entry && Date.now() - entry.ts <= EXPIRY_MS) {\n props.item_list_id = entry.source;\n if (Array.isArray(props.items)) {\n props.items = props.items.map((item) => ({ ...item, item_list_id: entry.source }));\n }\n }\n return;\n }\n\n if (normalizedEventType === EventType.AddToCart) {\n if (!Array.isArray(props.items)) return;\n const store = await loadStore();\n props.items = props.items.map((item) => {\n const productId = normalizeId(item.item_id, idPrefix);\n const entry = productId ? store[productId] : null;\n if (entry && Date.now() - entry.ts <= EXPIRY_MS) {\n return { ...item, item_list_id: entry.source };\n }\n return item;\n });\n const firstMatch = props.items.find((item) => item.item_list_id);\n if (firstMatch?.item_list_id) {\n props.item_list_id = firstMatch.item_list_id;\n }\n }\n}\n\nexport async function getAttribution(productId: string): Promise<string | null> {\n const store = await loadStore();\n const entry = store[String(productId)];\n if (entry && Date.now() - entry.ts < EXPIRY_MS) return entry.source;\n return null;\n}\n","import { GaEventType } from './constants';\nimport type { TrackProperties } from './types';\n\nfunction toSnakeCase(str: string): string {\n return str.replace(/-/g, '_');\n}\n\nexport interface GaSendOptions {\n gaProxyUrl: string;\n clientId: string;\n sessionId: string;\n numericSessionId: number;\n userId?: string | null;\n debug?: boolean;\n}\n\nexport async function sendToGA(\n eventType: string,\n props: TrackProperties,\n options: GaSendOptions\n): Promise<void> {\n const gaEvent = GaEventType[eventType] || toSnakeCase(eventType);\n const {\n items,\n currency,\n value,\n transaction_id,\n tax,\n shipping,\n coupon,\n ...rest\n } = props;\n\n const params: Record<string, unknown> = {\n session_id: options.numericSessionId,\n engagement_time_msec: 1,\n session_engaged: '1',\n };\n if (options.debug) params.debug_mode = true;\n\n if (currency) params.currency = currency;\n if (value !== undefined) params.value = value;\n if (transaction_id) params.transaction_id = transaction_id;\n if (tax !== undefined) params.tax = tax;\n if (shipping !== undefined) params.shipping = shipping;\n if (coupon) params.coupon = coupon;\n if (items) params.items = items;\n\n const passthroughKeys = [\n 'item_list_id',\n 'data_provider',\n 'event_source',\n 'id',\n 'search_term',\n 'total',\n 'total_text',\n 'total_vector',\n 'page_location',\n 'page_title',\n 'page_referrer',\n 'language',\n 'test_marker',\n 'yp_platform',\n 'yp_platform_version',\n 'yp_user_agent',\n ];\n for (const key of passthroughKeys) {\n if (rest[key] !== undefined) params[key] = rest[key];\n }\n\n const body: Record<string, unknown> = {\n client_id: options.clientId || options.sessionId,\n timestamp_micros: Date.now() * 1000,\n events: [{ name: gaEvent, params }],\n };\n\n if (options.userId) body.user_id = options.userId;\n\n const sep = options.gaProxyUrl.includes('?') ? '&' : '?';\n const url = options.debug\n ? `${options.gaProxyUrl}${sep}debug=1`\n : options.gaProxyUrl;\n\n try {\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n if (options.debug) {\n // eslint-disable-next-line no-console\n console.log(`[YesPlz Analytics] GA MP → ${gaEvent} (status ${res.status})`);\n }\n } catch (e) {\n if (options.debug) {\n // eslint-disable-next-line no-console\n console.log(`[YesPlz Analytics] GA MP error: ${(e as Error).message}`);\n }\n }\n}\n","import { Storage, StorageKeys } from './storage';\nimport type { ApiEvent } from './types';\n\nexport interface BeaconOptions {\n apiEndpoint: string;\n apiToken?: string | null;\n defaultParams?: Record<string, unknown>;\n idPrefix?: string;\n debounceMs?: number;\n debug?: boolean;\n}\n\nexport class Beacon {\n private queue: ApiEvent[] = [];\n private isSending = false;\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(private options: BeaconOptions) {}\n\n enqueue(event: ApiEvent): void {\n this.queue.push(event);\n this.scheduleSend();\n }\n\n enqueueAll(events: ApiEvent[]): void {\n this.queue.push(...events);\n this.scheduleSend();\n }\n\n private scheduleSend(): void {\n if (this.debounceTimer) clearTimeout(this.debounceTimer);\n this.debounceTimer = setTimeout(() => {\n void this.send();\n }, this.options.debounceMs ?? 1000);\n }\n\n async send(retryCount = 0): Promise<void> {\n if (this.queue.length === 0) return;\n if (!this.options.apiEndpoint) return;\n if (this.isSending) return;\n\n this.isSending = true;\n const eventsToSend = this.queue.splice(0, this.queue.length);\n\n const events = eventsToSend.map((event) => {\n const merged: Record<string, unknown> = {\n ...event,\n ...(this.options.defaultParams ?? {}),\n };\n const rawId = (event.extra_data as Record<string, unknown>).id;\n if (rawId && this.options.idPrefix) {\n merged.extra_data = {\n ...event.extra_data,\n id: `${this.options.idPrefix}${rawId}`,\n };\n }\n return merged;\n });\n\n try {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (this.options.apiToken) headers.Authorization = `Token ${this.options.apiToken}`;\n\n const res = await fetch(this.options.apiEndpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify(events),\n });\n\n if (res.status > 299) {\n throw new Error(`Failed to send events (status ${res.status})`);\n }\n\n if (this.options.debug) {\n // eslint-disable-next-line no-console\n console.log(`[YesPlz Analytics] Sync: ${events.length} events sent`);\n }\n await Storage.removeItem(StorageKeys.PENDING_EVENTS);\n } catch (e) {\n if (this.options.debug) {\n // eslint-disable-next-line no-console\n console.log(`[YesPlz Analytics] Sync failed: ${(e as Error).message}`);\n }\n this.queue.unshift(...eventsToSend);\n this.isSending = false;\n if (retryCount < 1) {\n setTimeout(() => void this.send(retryCount + 1), 2000);\n }\n return;\n }\n\n this.isSending = false;\n if (this.queue.length > 0) this.scheduleSend();\n }\n\n async flush(): Promise<void> {\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n await this.send();\n }\n\n async savePending(): Promise<void> {\n if (this.queue.length === 0) return;\n const toSave = this.queue.slice(-100);\n await Storage.setJSON(StorageKeys.PENDING_EVENTS, toSave);\n this.queue = [];\n }\n\n async restorePending(): Promise<void> {\n const pending = await Storage.getJSON<ApiEvent[]>(StorageKeys.PENDING_EVENTS, []);\n if (pending.length > 0) {\n this.queue.unshift(...pending);\n await Storage.removeItem(StorageKeys.PENDING_EVENTS);\n this.scheduleSend();\n }\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yesplz-ai/analytics-react-native",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "YesPlz Analytics SDK for React Native
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "YesPlz Analytics SDK for React Native - manual event tracking + interactions API + GA4 Measurement Protocol via shop proxy",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
7
7
|
"module": "./dist/index.js",
|
|
@@ -47,10 +47,10 @@
|
|
|
47
47
|
"@babel/preset-typescript": "^7.24.0",
|
|
48
48
|
"@react-native-async-storage/async-storage": "^2.0.0",
|
|
49
49
|
"@types/jest": "^29.5.14",
|
|
50
|
-
"@types/react": "^18.
|
|
50
|
+
"@types/react": "^18.2.0",
|
|
51
51
|
"babel-jest": "^29.7.0",
|
|
52
52
|
"jest": "^29.7.0",
|
|
53
|
-
"react": "
|
|
53
|
+
"react": "18.2.0",
|
|
54
54
|
"react-native": "^0.74.0",
|
|
55
55
|
"tsup": "^8.5.0",
|
|
56
56
|
"typescript": "^5.6.0"
|