@explorins/pers-shared 2.1.175 → 2.1.176

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.
@@ -78,6 +78,32 @@ export interface DataSource {
78
78
  * Full URL of the referring page.
79
79
  */
80
80
  referrer?: string;
81
+ /**
82
+ * Platform/device information.
83
+ * SDK provides this - backend stores as-is.
84
+ */
85
+ platform?: Platform;
86
+ }
87
+ /**
88
+ * Platform/device information for analytics.
89
+ * SDK is responsible for populating this accurately.
90
+ * Sent via x-platform header as JSON string.
91
+ */
92
+ export interface Platform {
93
+ /** Operating system: 'iOS', 'Android', 'Windows', 'macOS', 'Linux' */
94
+ os?: string;
95
+ /** OS version: '17.4', '14.0', '11' */
96
+ osVersion?: string;
97
+ /** Browser name (web only): 'Safari', 'Chrome', 'Firefox' */
98
+ browser?: string;
99
+ /** Browser version (web only): '125.0' */
100
+ browserVersion?: string;
101
+ /** App name (native only): 'MyApp' */
102
+ app?: string;
103
+ /** App version (native only): '2.3.1' */
104
+ appVersion?: string;
105
+ /** Device type: 'phone', 'tablet', 'desktop', 'kiosk' */
106
+ deviceType?: 'phone' | 'tablet' | 'desktop' | 'kiosk' | 'other';
81
107
  }
82
108
  /**
83
109
  * Type guard to check if a value is a valid DataSourceChannel.
@@ -87,4 +113,186 @@ export declare function isDataSourceChannel(value: unknown): value is DataSource
87
113
  * Default data source for manual/admin operations.
88
114
  */
89
115
  export declare const DEFAULT_DATA_SOURCE: DataSource;
116
+ /**
117
+ * Known domain mappings for auto-detecting source from referrer.
118
+ * Maps hostnames to normalized source names.
119
+ */
120
+ export declare const KNOWN_SOURCE_DOMAINS: Record<string, string>;
121
+ /**
122
+ * Auto-detect source from referrer URL domain.
123
+ * Maps common domains to friendly source names.
124
+ *
125
+ * @param referrer - Full referrer URL
126
+ * @returns Normalized source name or undefined
127
+ *
128
+ * @example
129
+ * detectSourceFromReferrer('https://www.google.com/search?q=test') // 'google'
130
+ * detectSourceFromReferrer('https://l.facebook.com/...') // 'facebook'
131
+ * detectSourceFromReferrer('https://partner.example.com') // 'example'
132
+ */
133
+ export declare function detectSourceFromReferrer(referrer?: string): string | undefined;
134
+ /**
135
+ * Auto-detect channel from User-Agent string.
136
+ *
137
+ * @param userAgent - User-Agent header value
138
+ * @param path - Optional request path for webhook detection
139
+ * @returns Detected channel
140
+ *
141
+ * @example
142
+ * detectChannelFromUserAgent('Mozilla/5.0 (iPhone; ...)') // 'mobile'
143
+ * detectChannelFromUserAgent('Mozilla/5.0 (Windows NT...)') // 'web'
144
+ * detectChannelFromUserAgent('', '/webhook/stripe') // 'webhook'
145
+ */
146
+ export declare function detectChannelFromUserAgent(userAgent?: string, path?: string): DataSourceChannel;
147
+ /**
148
+ * UTM parameters extracted from URLs.
149
+ * Standard marketing attribution fields from Google Analytics UTM format.
150
+ */
151
+ export interface UtmParams {
152
+ /** Traffic source (utm_source) - e.g., 'google', 'newsletter', 'partner_app' */
153
+ source?: string;
154
+ /** Marketing medium (utm_medium) - e.g., 'email', 'cpc', 'referral' */
155
+ medium?: string;
156
+ /** Campaign name (utm_campaign) - e.g., 'summer_promo_2026' */
157
+ campaign?: string;
158
+ /** Campaign term (utm_term) - e.g., 'running+shoes' (for paid search) */
159
+ term?: string;
160
+ /** Campaign content (utm_content) - e.g., 'logolink', 'textlink' */
161
+ content?: string;
162
+ }
163
+ /**
164
+ * Parse UTM parameters from a URL (deep link, referrer, etc.).
165
+ * Supports standard Google Analytics UTM parameters.
166
+ *
167
+ * @param url - Full URL containing UTM query parameters
168
+ * @returns Parsed UTM parameters object
169
+ *
170
+ * @example
171
+ * // Deep link from email campaign
172
+ * parseUtmParams('myapp://screen?utm_source=mailchimp&utm_medium=email&utm_campaign=summer_2026')
173
+ * // Returns: { source: 'mailchimp', medium: 'email', campaign: 'summer_2026' }
174
+ *
175
+ * @example
176
+ * // Web URL with full UTM tracking
177
+ * parseUtmParams('https://app.example.com?utm_source=google&utm_medium=cpc&utm_campaign=brand&utm_term=loyalty+app')
178
+ * // Returns: { source: 'google', medium: 'cpc', campaign: 'brand', term: 'loyalty+app' }
179
+ */
180
+ export declare function parseUtmParams(url: string): UtmParams;
181
+ /**
182
+ * SDK Data Source configuration for WEB applications.
183
+ *
184
+ * Web SDK should NOT send `channel` - backend auto-detects from User-Agent.
185
+ * Web SDK should NOT send `referrer` - browser sends HTTP Referer header automatically.
186
+ * Web SDK should NOT send `source` unless overriding auto-detection from referrer.
187
+ *
188
+ * @example
189
+ * // Minimal - backend handles everything
190
+ * sdk.configure({ dataSource: {} });
191
+ *
192
+ * // With campaign tracking (from URL params)
193
+ * const utm = parseUtmParams(window.location.href);
194
+ * sdk.configure({
195
+ * dataSource: {
196
+ * medium: utm.medium,
197
+ * campaign: utm.campaign,
198
+ * source: utm.source, // Optional: overrides referrer-based detection
199
+ * }
200
+ * });
201
+ */
202
+ export interface WebDataSourceConfig {
203
+ /**
204
+ * Marketing medium for attribution.
205
+ * Examples: 'email', 'cpc', 'referral', 'organic', 'paid', 'social', 'affiliate'
206
+ *
207
+ * Tip: Parse from utm_medium in URL.
208
+ */
209
+ medium?: string;
210
+ /**
211
+ * Campaign identifier for tracking.
212
+ * Examples: 'summer_promo_2026', 'welcome_series', 'partner_launch'
213
+ *
214
+ * Tip: Parse from utm_campaign in URL.
215
+ */
216
+ campaign?: string;
217
+ /**
218
+ * Traffic source override.
219
+ * Only set if you need to override auto-detection from referrer.
220
+ * Examples: 'mailchimp', 'partner_xyz', 'qr_code'
221
+ *
222
+ * Backend auto-detects from: HTTP Referer header → domain extraction
223
+ */
224
+ source?: string;
225
+ /**
226
+ * Referrer URL override.
227
+ * Only set in edge cases where browser doesn't send Referer header:
228
+ * - In-app webviews
229
+ * - Privacy browsers stripping referrer
230
+ * - Cross-origin iframe scenarios
231
+ */
232
+ referrer?: string;
233
+ }
234
+ /**
235
+ * SDK Data Source configuration for NATIVE mobile applications.
236
+ *
237
+ * Native apps MUST send `channel` since there's no User-Agent auto-detection.
238
+ * Native apps SHOULD send `source` when available (no referrer header exists).
239
+ *
240
+ * @example
241
+ * // Basic native app setup
242
+ * sdk.configure({
243
+ * dataSource: {
244
+ * channel: 'mobile',
245
+ * }
246
+ * });
247
+ *
248
+ * // Deep link with UTM tracking
249
+ * const deepLinkUrl = 'myapp://screen?utm_source=email&utm_medium=push&utm_campaign=retention';
250
+ * const utm = parseUtmParams(deepLinkUrl);
251
+ * sdk.configure({
252
+ * dataSource: {
253
+ * channel: 'mobile',
254
+ * source: utm.source, // 'email'
255
+ * medium: utm.medium, // 'push'
256
+ * campaign: utm.campaign, // 'retention'
257
+ * }
258
+ * });
259
+ *
260
+ * // QR code scan
261
+ * sdk.configure({
262
+ * dataSource: {
263
+ * channel: 'mobile',
264
+ * source: 'qr_code',
265
+ * medium: 'referral',
266
+ * campaign: 'lobby_checkin',
267
+ * }
268
+ * });
269
+ */
270
+ export interface NativeDataSourceConfig {
271
+ /**
272
+ * Primary ingestion channel - REQUIRED for native apps.
273
+ * Backend cannot auto-detect without browser User-Agent.
274
+ */
275
+ channel: 'mobile' | 'kiosk' | 'pos';
276
+ /**
277
+ * Marketing medium for attribution.
278
+ * Examples: 'push', 'deeplink', 'email', 'referral', 'organic'
279
+ */
280
+ medium?: string;
281
+ /**
282
+ * Campaign identifier for tracking.
283
+ * Examples: 'summer_promo_2026', 'onboarding_v3', 'retention_30d'
284
+ */
285
+ campaign?: string;
286
+ /**
287
+ * Traffic source - STRONGLY RECOMMENDED for native apps.
288
+ * No referrer header exists, so backend cannot auto-detect.
289
+ * Examples: 'push_notification', 'deep_link', 'qr_code', 'partner_app'
290
+ */
291
+ source?: string;
292
+ }
293
+ /**
294
+ * Combined SDK Data Source configuration.
295
+ * Use WebDataSourceConfig for web apps, NativeDataSourceConfig for native.
296
+ */
297
+ export type SdkDataSourceConfig = WebDataSourceConfig | NativeDataSourceConfig;
90
298
  //# sourceMappingURL=data-source.type.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"data-source.type.d.ts","sourceRoot":"","sources":["../../../../src/shared-lib/types/data-source.type.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH;;GAEG;AACH,eAAO,MAAM,oBAAoB,gGAUvB,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,OAAO,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAEpE;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,OAAO,EAAE,iBAAiB,CAAC;IAE3B;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,iBAAiB,CAE9E;AAED;;GAEG;AACH,eAAO,MAAM,mBAAmB,EAAE,UAEjC,CAAC"}
1
+ {"version":3,"file":"data-source.type.d.ts","sourceRoot":"","sources":["../../../../src/shared-lib/types/data-source.type.ts"],"names":[],"mappings":"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"}
@@ -43,8 +43,11 @@
43
43
  * };
44
44
  */
45
45
  Object.defineProperty(exports, "__esModule", { value: true });
46
- exports.DEFAULT_DATA_SOURCE = exports.DATA_SOURCE_CHANNELS = void 0;
46
+ exports.KNOWN_SOURCE_DOMAINS = exports.DEFAULT_DATA_SOURCE = exports.DATA_SOURCE_CHANNELS = void 0;
47
47
  exports.isDataSourceChannel = isDataSourceChannel;
48
+ exports.detectSourceFromReferrer = detectSourceFromReferrer;
49
+ exports.detectChannelFromUserAgent = detectChannelFromUserAgent;
50
+ exports.parseUtmParams = parseUtmParams;
48
51
  /**
49
52
  * Primary ingestion channels for data source tracking.
50
53
  */
@@ -71,4 +74,178 @@ function isDataSourceChannel(value) {
71
74
  exports.DEFAULT_DATA_SOURCE = {
72
75
  channel: 'admin',
73
76
  };
77
+ /**
78
+ * Known domain mappings for auto-detecting source from referrer.
79
+ * Maps hostnames to normalized source names.
80
+ */
81
+ exports.KNOWN_SOURCE_DOMAINS = {
82
+ // Google
83
+ 'google.com': 'google',
84
+ 'google.co.uk': 'google',
85
+ 'google.de': 'google',
86
+ 'google.fr': 'google',
87
+ 'google.es': 'google',
88
+ 'google.it': 'google',
89
+ 'google.nl': 'google',
90
+ 'google.pt': 'google',
91
+ 'google.pl': 'google',
92
+ 'google.ru': 'google',
93
+ 'google.com.br': 'google',
94
+ 'google.ca': 'google',
95
+ 'google.com.au': 'google',
96
+ 'google.co.jp': 'google',
97
+ 'google.co.in': 'google',
98
+ // Facebook
99
+ 'facebook.com': 'facebook',
100
+ 'fb.com': 'facebook',
101
+ 'm.facebook.com': 'facebook',
102
+ 'l.facebook.com': 'facebook',
103
+ 'lm.facebook.com': 'facebook',
104
+ // Instagram
105
+ 'instagram.com': 'instagram',
106
+ 'l.instagram.com': 'instagram',
107
+ // Twitter/X
108
+ 'twitter.com': 'twitter',
109
+ 'x.com': 'twitter',
110
+ 't.co': 'twitter',
111
+ 'mobile.twitter.com': 'twitter',
112
+ // LinkedIn
113
+ 'linkedin.com': 'linkedin',
114
+ 'lnkd.in': 'linkedin',
115
+ // YouTube
116
+ 'youtube.com': 'youtube',
117
+ 'youtu.be': 'youtube',
118
+ 'm.youtube.com': 'youtube',
119
+ // TikTok
120
+ 'tiktok.com': 'tiktok',
121
+ 'vm.tiktok.com': 'tiktok',
122
+ // Other social
123
+ 'pinterest.com': 'pinterest',
124
+ 'reddit.com': 'reddit',
125
+ 'tumblr.com': 'tumblr',
126
+ 'snapchat.com': 'snapchat',
127
+ // Search engines
128
+ 'bing.com': 'bing',
129
+ 'yahoo.com': 'yahoo',
130
+ 'duckduckgo.com': 'duckduckgo',
131
+ 'baidu.com': 'baidu',
132
+ 'yandex.com': 'yandex',
133
+ 'yandex.ru': 'yandex',
134
+ // Email providers (for tracking email clicks)
135
+ 'mail.google.com': 'gmail',
136
+ 'outlook.live.com': 'outlook',
137
+ 'outlook.office.com': 'outlook',
138
+ };
139
+ /**
140
+ * Auto-detect source from referrer URL domain.
141
+ * Maps common domains to friendly source names.
142
+ *
143
+ * @param referrer - Full referrer URL
144
+ * @returns Normalized source name or undefined
145
+ *
146
+ * @example
147
+ * detectSourceFromReferrer('https://www.google.com/search?q=test') // 'google'
148
+ * detectSourceFromReferrer('https://l.facebook.com/...') // 'facebook'
149
+ * detectSourceFromReferrer('https://partner.example.com') // 'example'
150
+ */
151
+ function detectSourceFromReferrer(referrer) {
152
+ if (!referrer)
153
+ return undefined;
154
+ try {
155
+ const url = new URL(referrer);
156
+ const hostname = url.hostname.toLowerCase().replace(/^www\./, '');
157
+ // Check exact match first
158
+ if (exports.KNOWN_SOURCE_DOMAINS[hostname]) {
159
+ return exports.KNOWN_SOURCE_DOMAINS[hostname];
160
+ }
161
+ // Check if hostname ends with known domain (for subdomains)
162
+ for (const [domain, source] of Object.entries(exports.KNOWN_SOURCE_DOMAINS)) {
163
+ if (hostname.endsWith('.' + domain)) {
164
+ return source;
165
+ }
166
+ }
167
+ // Fallback: extract main domain name (e.g., 'example' from 'mail.example.com')
168
+ const parts = hostname.split('.');
169
+ if (parts.length >= 2) {
170
+ return parts[parts.length - 2]; // Returns 'example' from 'sub.example.com'
171
+ }
172
+ return hostname;
173
+ }
174
+ catch {
175
+ // Invalid URL, return undefined
176
+ return undefined;
177
+ }
178
+ }
179
+ /**
180
+ * Auto-detect channel from User-Agent string.
181
+ *
182
+ * @param userAgent - User-Agent header value
183
+ * @param path - Optional request path for webhook detection
184
+ * @returns Detected channel
185
+ *
186
+ * @example
187
+ * detectChannelFromUserAgent('Mozilla/5.0 (iPhone; ...)') // 'mobile'
188
+ * detectChannelFromUserAgent('Mozilla/5.0 (Windows NT...)') // 'web'
189
+ * detectChannelFromUserAgent('', '/webhook/stripe') // 'webhook'
190
+ */
191
+ function detectChannelFromUserAgent(userAgent, path) {
192
+ // Check for webhook paths
193
+ if (path?.includes('/webhook')) {
194
+ return 'webhook';
195
+ }
196
+ const ua = (userAgent || '').toLowerCase();
197
+ // Check for mobile user-agents
198
+ if (/mobile|android|iphone|ipad|ipod|blackberry|windows phone/i.test(ua)) {
199
+ return 'mobile';
200
+ }
201
+ // Check for bot/crawler patterns (system)
202
+ if (/bot|crawler|spider|scraper|curl|wget|python|node-fetch|axios/i.test(ua)) {
203
+ return 'api';
204
+ }
205
+ // Default to web for browser-like user agents
206
+ return 'web';
207
+ }
208
+ /**
209
+ * Parse UTM parameters from a URL (deep link, referrer, etc.).
210
+ * Supports standard Google Analytics UTM parameters.
211
+ *
212
+ * @param url - Full URL containing UTM query parameters
213
+ * @returns Parsed UTM parameters object
214
+ *
215
+ * @example
216
+ * // Deep link from email campaign
217
+ * parseUtmParams('myapp://screen?utm_source=mailchimp&utm_medium=email&utm_campaign=summer_2026')
218
+ * // Returns: { source: 'mailchimp', medium: 'email', campaign: 'summer_2026' }
219
+ *
220
+ * @example
221
+ * // Web URL with full UTM tracking
222
+ * parseUtmParams('https://app.example.com?utm_source=google&utm_medium=cpc&utm_campaign=brand&utm_term=loyalty+app')
223
+ * // Returns: { source: 'google', medium: 'cpc', campaign: 'brand', term: 'loyalty+app' }
224
+ */
225
+ function parseUtmParams(url) {
226
+ const params = {};
227
+ try {
228
+ const urlObj = new URL(url);
229
+ const searchParams = urlObj.searchParams;
230
+ const source = searchParams.get('utm_source');
231
+ const medium = searchParams.get('utm_medium');
232
+ const campaign = searchParams.get('utm_campaign');
233
+ const term = searchParams.get('utm_term');
234
+ const content = searchParams.get('utm_content');
235
+ if (source)
236
+ params.source = source;
237
+ if (medium)
238
+ params.medium = medium;
239
+ if (campaign)
240
+ params.campaign = campaign;
241
+ if (term)
242
+ params.term = term;
243
+ if (content)
244
+ params.content = content;
245
+ }
246
+ catch {
247
+ // Invalid URL, return empty params
248
+ }
249
+ return params;
250
+ }
74
251
  //# sourceMappingURL=data-source.type.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"data-source.type.js","sourceRoot":"","sources":["../../../../src/shared-lib/types/data-source.type.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;;;AA4DH,kDAEC;AA5DD;;GAEG;AACU,QAAA,oBAAoB,GAAG;IAClC,KAAK,EAAQ,0BAA0B;IACvC,QAAQ,EAAK,2BAA2B;IACxC,KAAK,EAAQ,yBAAyB;IACtC,OAAO,EAAM,0BAA0B;IACvC,QAAQ,EAAK,+BAA+B;IAC5C,QAAQ,EAAK,yBAAyB;IACtC,SAAS,EAAI,4BAA4B;IACzC,MAAM,EAAO,uCAAuC;IACpD,WAAW,EAAE,iBAAiB;CACtB,CAAC;AA0CX;;GAEG;AACH,SAAgB,mBAAmB,CAAC,KAAc;IAChD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,4BAAoB,CAAC,QAAQ,CAAC,KAA0B,CAAC,CAAC;AAChG,CAAC;AAED;;GAEG;AACU,QAAA,mBAAmB,GAAe;IAC7C,OAAO,EAAE,OAAO;CACjB,CAAC"}
1
+ {"version":3,"file":"data-source.type.js","sourceRoot":"","sources":["../../../../src/shared-lib/types/data-source.type.ts"],"names":[],"mappings":"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"}
@@ -78,6 +78,32 @@ export interface DataSource {
78
78
  * Full URL of the referring page.
79
79
  */
80
80
  referrer?: string;
81
+ /**
82
+ * Platform/device information.
83
+ * SDK provides this - backend stores as-is.
84
+ */
85
+ platform?: Platform;
86
+ }
87
+ /**
88
+ * Platform/device information for analytics.
89
+ * SDK is responsible for populating this accurately.
90
+ * Sent via x-platform header as JSON string.
91
+ */
92
+ export interface Platform {
93
+ /** Operating system: 'iOS', 'Android', 'Windows', 'macOS', 'Linux' */
94
+ os?: string;
95
+ /** OS version: '17.4', '14.0', '11' */
96
+ osVersion?: string;
97
+ /** Browser name (web only): 'Safari', 'Chrome', 'Firefox' */
98
+ browser?: string;
99
+ /** Browser version (web only): '125.0' */
100
+ browserVersion?: string;
101
+ /** App name (native only): 'MyApp' */
102
+ app?: string;
103
+ /** App version (native only): '2.3.1' */
104
+ appVersion?: string;
105
+ /** Device type: 'phone', 'tablet', 'desktop', 'kiosk' */
106
+ deviceType?: 'phone' | 'tablet' | 'desktop' | 'kiosk' | 'other';
81
107
  }
82
108
  /**
83
109
  * Type guard to check if a value is a valid DataSourceChannel.
@@ -87,4 +113,186 @@ export declare function isDataSourceChannel(value: unknown): value is DataSource
87
113
  * Default data source for manual/admin operations.
88
114
  */
89
115
  export declare const DEFAULT_DATA_SOURCE: DataSource;
116
+ /**
117
+ * Known domain mappings for auto-detecting source from referrer.
118
+ * Maps hostnames to normalized source names.
119
+ */
120
+ export declare const KNOWN_SOURCE_DOMAINS: Record<string, string>;
121
+ /**
122
+ * Auto-detect source from referrer URL domain.
123
+ * Maps common domains to friendly source names.
124
+ *
125
+ * @param referrer - Full referrer URL
126
+ * @returns Normalized source name or undefined
127
+ *
128
+ * @example
129
+ * detectSourceFromReferrer('https://www.google.com/search?q=test') // 'google'
130
+ * detectSourceFromReferrer('https://l.facebook.com/...') // 'facebook'
131
+ * detectSourceFromReferrer('https://partner.example.com') // 'example'
132
+ */
133
+ export declare function detectSourceFromReferrer(referrer?: string): string | undefined;
134
+ /**
135
+ * Auto-detect channel from User-Agent string.
136
+ *
137
+ * @param userAgent - User-Agent header value
138
+ * @param path - Optional request path for webhook detection
139
+ * @returns Detected channel
140
+ *
141
+ * @example
142
+ * detectChannelFromUserAgent('Mozilla/5.0 (iPhone; ...)') // 'mobile'
143
+ * detectChannelFromUserAgent('Mozilla/5.0 (Windows NT...)') // 'web'
144
+ * detectChannelFromUserAgent('', '/webhook/stripe') // 'webhook'
145
+ */
146
+ export declare function detectChannelFromUserAgent(userAgent?: string, path?: string): DataSourceChannel;
147
+ /**
148
+ * UTM parameters extracted from URLs.
149
+ * Standard marketing attribution fields from Google Analytics UTM format.
150
+ */
151
+ export interface UtmParams {
152
+ /** Traffic source (utm_source) - e.g., 'google', 'newsletter', 'partner_app' */
153
+ source?: string;
154
+ /** Marketing medium (utm_medium) - e.g., 'email', 'cpc', 'referral' */
155
+ medium?: string;
156
+ /** Campaign name (utm_campaign) - e.g., 'summer_promo_2026' */
157
+ campaign?: string;
158
+ /** Campaign term (utm_term) - e.g., 'running+shoes' (for paid search) */
159
+ term?: string;
160
+ /** Campaign content (utm_content) - e.g., 'logolink', 'textlink' */
161
+ content?: string;
162
+ }
163
+ /**
164
+ * Parse UTM parameters from a URL (deep link, referrer, etc.).
165
+ * Supports standard Google Analytics UTM parameters.
166
+ *
167
+ * @param url - Full URL containing UTM query parameters
168
+ * @returns Parsed UTM parameters object
169
+ *
170
+ * @example
171
+ * // Deep link from email campaign
172
+ * parseUtmParams('myapp://screen?utm_source=mailchimp&utm_medium=email&utm_campaign=summer_2026')
173
+ * // Returns: { source: 'mailchimp', medium: 'email', campaign: 'summer_2026' }
174
+ *
175
+ * @example
176
+ * // Web URL with full UTM tracking
177
+ * parseUtmParams('https://app.example.com?utm_source=google&utm_medium=cpc&utm_campaign=brand&utm_term=loyalty+app')
178
+ * // Returns: { source: 'google', medium: 'cpc', campaign: 'brand', term: 'loyalty+app' }
179
+ */
180
+ export declare function parseUtmParams(url: string): UtmParams;
181
+ /**
182
+ * SDK Data Source configuration for WEB applications.
183
+ *
184
+ * Web SDK should NOT send `channel` - backend auto-detects from User-Agent.
185
+ * Web SDK should NOT send `referrer` - browser sends HTTP Referer header automatically.
186
+ * Web SDK should NOT send `source` unless overriding auto-detection from referrer.
187
+ *
188
+ * @example
189
+ * // Minimal - backend handles everything
190
+ * sdk.configure({ dataSource: {} });
191
+ *
192
+ * // With campaign tracking (from URL params)
193
+ * const utm = parseUtmParams(window.location.href);
194
+ * sdk.configure({
195
+ * dataSource: {
196
+ * medium: utm.medium,
197
+ * campaign: utm.campaign,
198
+ * source: utm.source, // Optional: overrides referrer-based detection
199
+ * }
200
+ * });
201
+ */
202
+ export interface WebDataSourceConfig {
203
+ /**
204
+ * Marketing medium for attribution.
205
+ * Examples: 'email', 'cpc', 'referral', 'organic', 'paid', 'social', 'affiliate'
206
+ *
207
+ * Tip: Parse from utm_medium in URL.
208
+ */
209
+ medium?: string;
210
+ /**
211
+ * Campaign identifier for tracking.
212
+ * Examples: 'summer_promo_2026', 'welcome_series', 'partner_launch'
213
+ *
214
+ * Tip: Parse from utm_campaign in URL.
215
+ */
216
+ campaign?: string;
217
+ /**
218
+ * Traffic source override.
219
+ * Only set if you need to override auto-detection from referrer.
220
+ * Examples: 'mailchimp', 'partner_xyz', 'qr_code'
221
+ *
222
+ * Backend auto-detects from: HTTP Referer header → domain extraction
223
+ */
224
+ source?: string;
225
+ /**
226
+ * Referrer URL override.
227
+ * Only set in edge cases where browser doesn't send Referer header:
228
+ * - In-app webviews
229
+ * - Privacy browsers stripping referrer
230
+ * - Cross-origin iframe scenarios
231
+ */
232
+ referrer?: string;
233
+ }
234
+ /**
235
+ * SDK Data Source configuration for NATIVE mobile applications.
236
+ *
237
+ * Native apps MUST send `channel` since there's no User-Agent auto-detection.
238
+ * Native apps SHOULD send `source` when available (no referrer header exists).
239
+ *
240
+ * @example
241
+ * // Basic native app setup
242
+ * sdk.configure({
243
+ * dataSource: {
244
+ * channel: 'mobile',
245
+ * }
246
+ * });
247
+ *
248
+ * // Deep link with UTM tracking
249
+ * const deepLinkUrl = 'myapp://screen?utm_source=email&utm_medium=push&utm_campaign=retention';
250
+ * const utm = parseUtmParams(deepLinkUrl);
251
+ * sdk.configure({
252
+ * dataSource: {
253
+ * channel: 'mobile',
254
+ * source: utm.source, // 'email'
255
+ * medium: utm.medium, // 'push'
256
+ * campaign: utm.campaign, // 'retention'
257
+ * }
258
+ * });
259
+ *
260
+ * // QR code scan
261
+ * sdk.configure({
262
+ * dataSource: {
263
+ * channel: 'mobile',
264
+ * source: 'qr_code',
265
+ * medium: 'referral',
266
+ * campaign: 'lobby_checkin',
267
+ * }
268
+ * });
269
+ */
270
+ export interface NativeDataSourceConfig {
271
+ /**
272
+ * Primary ingestion channel - REQUIRED for native apps.
273
+ * Backend cannot auto-detect without browser User-Agent.
274
+ */
275
+ channel: 'mobile' | 'kiosk' | 'pos';
276
+ /**
277
+ * Marketing medium for attribution.
278
+ * Examples: 'push', 'deeplink', 'email', 'referral', 'organic'
279
+ */
280
+ medium?: string;
281
+ /**
282
+ * Campaign identifier for tracking.
283
+ * Examples: 'summer_promo_2026', 'onboarding_v3', 'retention_30d'
284
+ */
285
+ campaign?: string;
286
+ /**
287
+ * Traffic source - STRONGLY RECOMMENDED for native apps.
288
+ * No referrer header exists, so backend cannot auto-detect.
289
+ * Examples: 'push_notification', 'deep_link', 'qr_code', 'partner_app'
290
+ */
291
+ source?: string;
292
+ }
293
+ /**
294
+ * Combined SDK Data Source configuration.
295
+ * Use WebDataSourceConfig for web apps, NativeDataSourceConfig for native.
296
+ */
297
+ export type SdkDataSourceConfig = WebDataSourceConfig | NativeDataSourceConfig;
90
298
  //# sourceMappingURL=data-source.type.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"data-source.type.d.ts","sourceRoot":"","sources":["../../../../src/shared-lib/types/data-source.type.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH;;GAEG;AACH,eAAO,MAAM,oBAAoB,gGAUvB,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,OAAO,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAEpE;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,OAAO,EAAE,iBAAiB,CAAC;IAE3B;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,iBAAiB,CAE9E;AAED;;GAEG;AACH,eAAO,MAAM,mBAAmB,EAAE,UAEjC,CAAC"}
1
+ {"version":3,"file":"data-source.type.d.ts","sourceRoot":"","sources":["../../../../src/shared-lib/types/data-source.type.ts"],"names":[],"mappings":"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"}
@@ -67,4 +67,178 @@ export function isDataSourceChannel(value) {
67
67
  export const DEFAULT_DATA_SOURCE = {
68
68
  channel: 'admin',
69
69
  };
70
+ /**
71
+ * Known domain mappings for auto-detecting source from referrer.
72
+ * Maps hostnames to normalized source names.
73
+ */
74
+ export const KNOWN_SOURCE_DOMAINS = {
75
+ // Google
76
+ 'google.com': 'google',
77
+ 'google.co.uk': 'google',
78
+ 'google.de': 'google',
79
+ 'google.fr': 'google',
80
+ 'google.es': 'google',
81
+ 'google.it': 'google',
82
+ 'google.nl': 'google',
83
+ 'google.pt': 'google',
84
+ 'google.pl': 'google',
85
+ 'google.ru': 'google',
86
+ 'google.com.br': 'google',
87
+ 'google.ca': 'google',
88
+ 'google.com.au': 'google',
89
+ 'google.co.jp': 'google',
90
+ 'google.co.in': 'google',
91
+ // Facebook
92
+ 'facebook.com': 'facebook',
93
+ 'fb.com': 'facebook',
94
+ 'm.facebook.com': 'facebook',
95
+ 'l.facebook.com': 'facebook',
96
+ 'lm.facebook.com': 'facebook',
97
+ // Instagram
98
+ 'instagram.com': 'instagram',
99
+ 'l.instagram.com': 'instagram',
100
+ // Twitter/X
101
+ 'twitter.com': 'twitter',
102
+ 'x.com': 'twitter',
103
+ 't.co': 'twitter',
104
+ 'mobile.twitter.com': 'twitter',
105
+ // LinkedIn
106
+ 'linkedin.com': 'linkedin',
107
+ 'lnkd.in': 'linkedin',
108
+ // YouTube
109
+ 'youtube.com': 'youtube',
110
+ 'youtu.be': 'youtube',
111
+ 'm.youtube.com': 'youtube',
112
+ // TikTok
113
+ 'tiktok.com': 'tiktok',
114
+ 'vm.tiktok.com': 'tiktok',
115
+ // Other social
116
+ 'pinterest.com': 'pinterest',
117
+ 'reddit.com': 'reddit',
118
+ 'tumblr.com': 'tumblr',
119
+ 'snapchat.com': 'snapchat',
120
+ // Search engines
121
+ 'bing.com': 'bing',
122
+ 'yahoo.com': 'yahoo',
123
+ 'duckduckgo.com': 'duckduckgo',
124
+ 'baidu.com': 'baidu',
125
+ 'yandex.com': 'yandex',
126
+ 'yandex.ru': 'yandex',
127
+ // Email providers (for tracking email clicks)
128
+ 'mail.google.com': 'gmail',
129
+ 'outlook.live.com': 'outlook',
130
+ 'outlook.office.com': 'outlook',
131
+ };
132
+ /**
133
+ * Auto-detect source from referrer URL domain.
134
+ * Maps common domains to friendly source names.
135
+ *
136
+ * @param referrer - Full referrer URL
137
+ * @returns Normalized source name or undefined
138
+ *
139
+ * @example
140
+ * detectSourceFromReferrer('https://www.google.com/search?q=test') // 'google'
141
+ * detectSourceFromReferrer('https://l.facebook.com/...') // 'facebook'
142
+ * detectSourceFromReferrer('https://partner.example.com') // 'example'
143
+ */
144
+ export function detectSourceFromReferrer(referrer) {
145
+ if (!referrer)
146
+ return undefined;
147
+ try {
148
+ const url = new URL(referrer);
149
+ const hostname = url.hostname.toLowerCase().replace(/^www\./, '');
150
+ // Check exact match first
151
+ if (KNOWN_SOURCE_DOMAINS[hostname]) {
152
+ return KNOWN_SOURCE_DOMAINS[hostname];
153
+ }
154
+ // Check if hostname ends with known domain (for subdomains)
155
+ for (const [domain, source] of Object.entries(KNOWN_SOURCE_DOMAINS)) {
156
+ if (hostname.endsWith('.' + domain)) {
157
+ return source;
158
+ }
159
+ }
160
+ // Fallback: extract main domain name (e.g., 'example' from 'mail.example.com')
161
+ const parts = hostname.split('.');
162
+ if (parts.length >= 2) {
163
+ return parts[parts.length - 2]; // Returns 'example' from 'sub.example.com'
164
+ }
165
+ return hostname;
166
+ }
167
+ catch {
168
+ // Invalid URL, return undefined
169
+ return undefined;
170
+ }
171
+ }
172
+ /**
173
+ * Auto-detect channel from User-Agent string.
174
+ *
175
+ * @param userAgent - User-Agent header value
176
+ * @param path - Optional request path for webhook detection
177
+ * @returns Detected channel
178
+ *
179
+ * @example
180
+ * detectChannelFromUserAgent('Mozilla/5.0 (iPhone; ...)') // 'mobile'
181
+ * detectChannelFromUserAgent('Mozilla/5.0 (Windows NT...)') // 'web'
182
+ * detectChannelFromUserAgent('', '/webhook/stripe') // 'webhook'
183
+ */
184
+ export function detectChannelFromUserAgent(userAgent, path) {
185
+ // Check for webhook paths
186
+ if (path?.includes('/webhook')) {
187
+ return 'webhook';
188
+ }
189
+ const ua = (userAgent || '').toLowerCase();
190
+ // Check for mobile user-agents
191
+ if (/mobile|android|iphone|ipad|ipod|blackberry|windows phone/i.test(ua)) {
192
+ return 'mobile';
193
+ }
194
+ // Check for bot/crawler patterns (system)
195
+ if (/bot|crawler|spider|scraper|curl|wget|python|node-fetch|axios/i.test(ua)) {
196
+ return 'api';
197
+ }
198
+ // Default to web for browser-like user agents
199
+ return 'web';
200
+ }
201
+ /**
202
+ * Parse UTM parameters from a URL (deep link, referrer, etc.).
203
+ * Supports standard Google Analytics UTM parameters.
204
+ *
205
+ * @param url - Full URL containing UTM query parameters
206
+ * @returns Parsed UTM parameters object
207
+ *
208
+ * @example
209
+ * // Deep link from email campaign
210
+ * parseUtmParams('myapp://screen?utm_source=mailchimp&utm_medium=email&utm_campaign=summer_2026')
211
+ * // Returns: { source: 'mailchimp', medium: 'email', campaign: 'summer_2026' }
212
+ *
213
+ * @example
214
+ * // Web URL with full UTM tracking
215
+ * parseUtmParams('https://app.example.com?utm_source=google&utm_medium=cpc&utm_campaign=brand&utm_term=loyalty+app')
216
+ * // Returns: { source: 'google', medium: 'cpc', campaign: 'brand', term: 'loyalty+app' }
217
+ */
218
+ export function parseUtmParams(url) {
219
+ const params = {};
220
+ try {
221
+ const urlObj = new URL(url);
222
+ const searchParams = urlObj.searchParams;
223
+ const source = searchParams.get('utm_source');
224
+ const medium = searchParams.get('utm_medium');
225
+ const campaign = searchParams.get('utm_campaign');
226
+ const term = searchParams.get('utm_term');
227
+ const content = searchParams.get('utm_content');
228
+ if (source)
229
+ params.source = source;
230
+ if (medium)
231
+ params.medium = medium;
232
+ if (campaign)
233
+ params.campaign = campaign;
234
+ if (term)
235
+ params.term = term;
236
+ if (content)
237
+ params.content = content;
238
+ }
239
+ catch {
240
+ // Invalid URL, return empty params
241
+ }
242
+ return params;
243
+ }
70
244
  //# sourceMappingURL=data-source.type.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"data-source.type.js","sourceRoot":"","sources":["../../../../src/shared-lib/types/data-source.type.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,KAAK,EAAQ,0BAA0B;IACvC,QAAQ,EAAK,2BAA2B;IACxC,KAAK,EAAQ,yBAAyB;IACtC,OAAO,EAAM,0BAA0B;IACvC,QAAQ,EAAK,+BAA+B;IAC5C,QAAQ,EAAK,yBAAyB;IACtC,SAAS,EAAI,4BAA4B;IACzC,MAAM,EAAO,uCAAuC;IACpD,WAAW,EAAE,iBAAiB;CACtB,CAAC;AA0CX;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAc;IAChD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,oBAAoB,CAAC,QAAQ,CAAC,KAA0B,CAAC,CAAC;AAChG,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAe;IAC7C,OAAO,EAAE,OAAO;CACjB,CAAC"}
1
+ {"version":3,"file":"data-source.type.js","sourceRoot":"","sources":["../../../../src/shared-lib/types/data-source.type.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@explorins/pers-shared",
3
- "version": "2.1.175",
3
+ "version": "2.1.176",
4
4
  "scripts": {
5
5
  "clean": "find dist -type f -delete 2>/dev/null || true",
6
6
  "build:esm": "tsc -p tsconfig.esm.json && node scripts/add-js-extensions.js",