getu-attribution-v2-sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +775 -0
- package/dist/core/AttributionSDK.d.ts +63 -0
- package/dist/core/AttributionSDK.d.ts.map +1 -0
- package/dist/core/AttributionSDK.js +709 -0
- package/dist/getuai-attribution.min.js +1 -0
- package/dist/index.d.ts +85 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.esm.js +1859 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +2017 -0
- package/dist/queue/index.d.ts +51 -0
- package/dist/queue/index.d.ts.map +1 -0
- package/dist/queue/index.js +215 -0
- package/dist/storage/index.d.ts +46 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +363 -0
- package/dist/types/index.d.ts +101 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +32 -0
- package/dist/utils/index.d.ts +36 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +297 -0
- package/package.json +63 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
export declare enum EventType {
|
|
2
|
+
PAGE_VIEW = "page_view",
|
|
3
|
+
VIDEO_PLAY = "video_play",
|
|
4
|
+
FORM_SUBMIT = "form_submit",
|
|
5
|
+
EMAIL_VERIFICATION = "email_verification",
|
|
6
|
+
LOGIN = "login",
|
|
7
|
+
SIGNUP = "signup",
|
|
8
|
+
PRODUCT_VIEW = "product_view",
|
|
9
|
+
ADD_TO_CART = "add_to_cart",
|
|
10
|
+
PURCHASE = "purchase"
|
|
11
|
+
}
|
|
12
|
+
export declare enum Currency {
|
|
13
|
+
USD = "USD"
|
|
14
|
+
}
|
|
15
|
+
export interface UTMData {
|
|
16
|
+
utm_source?: string | null;
|
|
17
|
+
utm_medium?: string | null;
|
|
18
|
+
utm_campaign?: string | null;
|
|
19
|
+
utm_term?: string | null;
|
|
20
|
+
utm_content?: string | null;
|
|
21
|
+
timestamp: number;
|
|
22
|
+
}
|
|
23
|
+
export interface AttributionData {
|
|
24
|
+
firstTouch: UTMData;
|
|
25
|
+
lastTouch: UTMData;
|
|
26
|
+
touchpoints: UTMData[];
|
|
27
|
+
expiresAt: number;
|
|
28
|
+
}
|
|
29
|
+
export interface EventData {
|
|
30
|
+
event_id: string;
|
|
31
|
+
event_type: EventType;
|
|
32
|
+
tracking_user_id?: string;
|
|
33
|
+
utm_source?: string | null;
|
|
34
|
+
utm_medium?: string | null;
|
|
35
|
+
utm_campaign?: string | null;
|
|
36
|
+
utm_term?: string | null;
|
|
37
|
+
utm_content?: string | null;
|
|
38
|
+
revenue?: number | null;
|
|
39
|
+
currency?: Currency | null;
|
|
40
|
+
event_data?: Record<string, any> | null;
|
|
41
|
+
context?: {
|
|
42
|
+
page?: {
|
|
43
|
+
domain?: string | null;
|
|
44
|
+
path?: string | null;
|
|
45
|
+
title?: string | null;
|
|
46
|
+
referrer?: string | null;
|
|
47
|
+
url?: string | null;
|
|
48
|
+
querystring?: string | null;
|
|
49
|
+
query_params?: Record<string, string> | null;
|
|
50
|
+
};
|
|
51
|
+
[key: string]: any;
|
|
52
|
+
} | null;
|
|
53
|
+
timestamp?: number;
|
|
54
|
+
}
|
|
55
|
+
export interface BatchEventRequest {
|
|
56
|
+
events: EventData[];
|
|
57
|
+
}
|
|
58
|
+
export declare const defaultEndpoint = "https://attribution.getu.ai/attribution/api";
|
|
59
|
+
export interface SDKConfig {
|
|
60
|
+
apiKey: string;
|
|
61
|
+
apiEndpoint?: string;
|
|
62
|
+
batchSize?: number;
|
|
63
|
+
batchInterval?: number;
|
|
64
|
+
maxRetries?: number;
|
|
65
|
+
retryDelay?: number;
|
|
66
|
+
enableDebug?: boolean;
|
|
67
|
+
autoTrack?: boolean;
|
|
68
|
+
autoTrackPageView?: boolean;
|
|
69
|
+
sessionTimeout?: number;
|
|
70
|
+
enableCrossDomainUTM?: boolean;
|
|
71
|
+
crossDomainUTMParams?: string[];
|
|
72
|
+
excludeDomains?: string[];
|
|
73
|
+
autoCleanUTM?: boolean;
|
|
74
|
+
pageViewDebounceInterval?: number;
|
|
75
|
+
}
|
|
76
|
+
export interface StorageInterface {
|
|
77
|
+
get(key: string): any;
|
|
78
|
+
set(key: string, value: any): void;
|
|
79
|
+
remove(key: string): void;
|
|
80
|
+
clear(): void;
|
|
81
|
+
}
|
|
82
|
+
export interface QueueInterface {
|
|
83
|
+
add(event: EventData): void;
|
|
84
|
+
process(): Promise<void>;
|
|
85
|
+
clear(): void;
|
|
86
|
+
size(): number;
|
|
87
|
+
}
|
|
88
|
+
export interface LoggerInterface {
|
|
89
|
+
debug(message: string, ...args: any[]): void;
|
|
90
|
+
info(message: string, ...args: any[]): void;
|
|
91
|
+
warn(message: string, ...args: any[]): void;
|
|
92
|
+
error(message: string, ...args: any[]): void;
|
|
93
|
+
}
|
|
94
|
+
export interface UserSession {
|
|
95
|
+
sessionId: string;
|
|
96
|
+
startTime: number;
|
|
97
|
+
lastActivity: number;
|
|
98
|
+
pageViews: number;
|
|
99
|
+
}
|
|
100
|
+
export declare const IMMEDIATE_EVENTS: EventType[];
|
|
101
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Event types matching server-side enum exactly
|
|
2
|
+
export var EventType;
|
|
3
|
+
(function (EventType) {
|
|
4
|
+
// Pre-conversion signals
|
|
5
|
+
EventType["PAGE_VIEW"] = "page_view";
|
|
6
|
+
EventType["VIDEO_PLAY"] = "video_play";
|
|
7
|
+
// Registration funnel
|
|
8
|
+
EventType["FORM_SUBMIT"] = "form_submit";
|
|
9
|
+
EventType["EMAIL_VERIFICATION"] = "email_verification";
|
|
10
|
+
// Login flow
|
|
11
|
+
EventType["LOGIN"] = "login";
|
|
12
|
+
// Signup flow
|
|
13
|
+
EventType["SIGNUP"] = "signup";
|
|
14
|
+
// Purchase funnel
|
|
15
|
+
EventType["PRODUCT_VIEW"] = "product_view";
|
|
16
|
+
EventType["ADD_TO_CART"] = "add_to_cart";
|
|
17
|
+
EventType["PURCHASE"] = "purchase";
|
|
18
|
+
})(EventType || (EventType = {}));
|
|
19
|
+
// Currency types
|
|
20
|
+
export var Currency;
|
|
21
|
+
(function (Currency) {
|
|
22
|
+
Currency["USD"] = "USD";
|
|
23
|
+
})(Currency || (Currency = {}));
|
|
24
|
+
export const defaultEndpoint = "https://attribution.getu.ai/attribution/api";
|
|
25
|
+
// Special events that should be sent immediately
|
|
26
|
+
export const IMMEDIATE_EVENTS = [
|
|
27
|
+
EventType.PURCHASE,
|
|
28
|
+
EventType.LOGIN,
|
|
29
|
+
EventType.SIGNUP,
|
|
30
|
+
EventType.FORM_SUBMIT,
|
|
31
|
+
EventType.EMAIL_VERIFICATION,
|
|
32
|
+
];
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { LoggerInterface, UTMData } from "../types";
|
|
2
|
+
export declare function generateId(): string;
|
|
3
|
+
export declare function getTimestamp(): number;
|
|
4
|
+
export declare function parseUrlParams(url: string): Record<string, string>;
|
|
5
|
+
export declare function extractUTMParams(url: string): Record<string, string>;
|
|
6
|
+
export declare function isLocalStorageSupported(): boolean;
|
|
7
|
+
export declare function isIndexedDBSupported(): boolean;
|
|
8
|
+
export declare function deepClone<T>(obj: T): T;
|
|
9
|
+
export declare function debounce<T extends (...args: any[]) => any>(func: T, wait: number): (...args: Parameters<T>) => void;
|
|
10
|
+
export declare function throttle<T extends (...args: any[]) => any>(func: T, limit: number): (...args: Parameters<T>) => void;
|
|
11
|
+
export declare function retry<T>(fn: () => Promise<T>, maxRetries?: number, baseDelay?: number): Promise<T>;
|
|
12
|
+
export declare class ConsoleLogger implements LoggerInterface {
|
|
13
|
+
private enabled;
|
|
14
|
+
constructor(enabled?: boolean);
|
|
15
|
+
debug(message: string, ...args: any[]): void;
|
|
16
|
+
info(message: string, ...args: any[]): void;
|
|
17
|
+
warn(message: string, ...args: any[]): void;
|
|
18
|
+
error(message: string, ...args: any[]): void;
|
|
19
|
+
}
|
|
20
|
+
export declare function getUserAgent(): string;
|
|
21
|
+
export declare function getReferrer(): string;
|
|
22
|
+
export declare function getCurrentUrl(): string;
|
|
23
|
+
export declare function getPageTitle(): string;
|
|
24
|
+
export declare function isOnline(): boolean;
|
|
25
|
+
export declare function generateSessionId(): string;
|
|
26
|
+
export declare function isValidEmail(email: string): boolean;
|
|
27
|
+
export declare function formatCurrency(amount: number, currency?: string): string;
|
|
28
|
+
export declare function addUTMToURL(url: string, utmParams: Record<string, string>): string;
|
|
29
|
+
export declare function shouldExcludeDomain(url: string, excludeDomains?: string[]): boolean;
|
|
30
|
+
export declare function getDomainFromURL(url: string): string | null;
|
|
31
|
+
export declare function isExternalURL(url: string): boolean;
|
|
32
|
+
export declare function filterUTMParams(utmData: Partial<UTMData>, allowedParams?: string[]): Record<string, string>;
|
|
33
|
+
export declare function getQueryString(url?: string): string;
|
|
34
|
+
export declare function getQueryParams(url?: string): Record<string, string>;
|
|
35
|
+
export declare function cleanURL(): void;
|
|
36
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
// Generate unique ID
|
|
2
|
+
export function generateId() {
|
|
3
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
|
|
4
|
+
const r = (Math.random() * 16) | 0;
|
|
5
|
+
const v = c === "x" ? r : (r & 0x3) | 0x8;
|
|
6
|
+
return v.toString(16);
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
// Generate timestamp in seconds
|
|
10
|
+
export function getTimestamp() {
|
|
11
|
+
return Math.floor(Date.now() / 1000);
|
|
12
|
+
}
|
|
13
|
+
// Parse URL parameters
|
|
14
|
+
export function parseUrlParams(url) {
|
|
15
|
+
const params = {};
|
|
16
|
+
try {
|
|
17
|
+
const urlObj = new URL(url);
|
|
18
|
+
urlObj.searchParams.forEach((value, key) => {
|
|
19
|
+
params[key] = value;
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
// Handle invalid URLs
|
|
24
|
+
}
|
|
25
|
+
return params;
|
|
26
|
+
}
|
|
27
|
+
// Extract UTM parameters from URL
|
|
28
|
+
export function extractUTMParams(url) {
|
|
29
|
+
const params = parseUrlParams(url);
|
|
30
|
+
const utmParams = {};
|
|
31
|
+
const utmKeys = [
|
|
32
|
+
"utm_source",
|
|
33
|
+
"utm_medium",
|
|
34
|
+
"utm_campaign",
|
|
35
|
+
"utm_term",
|
|
36
|
+
"utm_content",
|
|
37
|
+
];
|
|
38
|
+
utmKeys.forEach((key) => {
|
|
39
|
+
if (params[key] && params[key].trim() !== "") {
|
|
40
|
+
utmParams[key] = params[key].trim();
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
return utmParams;
|
|
44
|
+
}
|
|
45
|
+
// Check if browser supports localStorage
|
|
46
|
+
export function isLocalStorageSupported() {
|
|
47
|
+
try {
|
|
48
|
+
const test = "__localStorage_test__";
|
|
49
|
+
localStorage.setItem(test, test);
|
|
50
|
+
localStorage.removeItem(test);
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// Check if browser supports IndexedDB
|
|
58
|
+
export function isIndexedDBSupported() {
|
|
59
|
+
return "indexedDB" in window;
|
|
60
|
+
}
|
|
61
|
+
// Deep clone object
|
|
62
|
+
export function deepClone(obj) {
|
|
63
|
+
if (obj === null || typeof obj !== "object") {
|
|
64
|
+
return obj;
|
|
65
|
+
}
|
|
66
|
+
if (obj instanceof Date) {
|
|
67
|
+
return new Date(obj.getTime());
|
|
68
|
+
}
|
|
69
|
+
if (obj instanceof Array) {
|
|
70
|
+
return obj.map((item) => deepClone(item));
|
|
71
|
+
}
|
|
72
|
+
if (typeof obj === "object") {
|
|
73
|
+
const cloned = {};
|
|
74
|
+
for (const key in obj) {
|
|
75
|
+
if (obj.hasOwnProperty(key)) {
|
|
76
|
+
cloned[key] = deepClone(obj[key]);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return cloned;
|
|
80
|
+
}
|
|
81
|
+
return obj;
|
|
82
|
+
}
|
|
83
|
+
// Debounce function
|
|
84
|
+
export function debounce(func, wait) {
|
|
85
|
+
let timeout;
|
|
86
|
+
return (...args) => {
|
|
87
|
+
clearTimeout(timeout);
|
|
88
|
+
timeout = setTimeout(() => func(...args), wait);
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
// Throttle function
|
|
92
|
+
export function throttle(func, limit) {
|
|
93
|
+
let inThrottle;
|
|
94
|
+
return (...args) => {
|
|
95
|
+
if (!inThrottle) {
|
|
96
|
+
func(...args);
|
|
97
|
+
inThrottle = true;
|
|
98
|
+
setTimeout(() => (inThrottle = false), limit);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
// Retry function with exponential backoff
|
|
103
|
+
export async function retry(fn, maxRetries = 3, baseDelay = 1000) {
|
|
104
|
+
let lastError;
|
|
105
|
+
for (let i = 0; i <= maxRetries; i++) {
|
|
106
|
+
try {
|
|
107
|
+
return await fn();
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
lastError = error;
|
|
111
|
+
if (i === maxRetries) {
|
|
112
|
+
throw lastError;
|
|
113
|
+
}
|
|
114
|
+
const delay = baseDelay * Math.pow(2, i);
|
|
115
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
throw lastError;
|
|
119
|
+
}
|
|
120
|
+
// Console logger implementation
|
|
121
|
+
export class ConsoleLogger {
|
|
122
|
+
constructor(enabled = true) {
|
|
123
|
+
this.enabled = enabled;
|
|
124
|
+
}
|
|
125
|
+
debug(message, ...args) {
|
|
126
|
+
if (this.enabled && console.debug) {
|
|
127
|
+
console.debug(`[GetuAI Debug] ${message}`, ...args);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
info(message, ...args) {
|
|
131
|
+
if (this.enabled && console.info) {
|
|
132
|
+
console.info(`[GetuAI Info] ${message}`, ...args);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
warn(message, ...args) {
|
|
136
|
+
if (this.enabled && console.warn) {
|
|
137
|
+
console.warn(`[GetuAI Warn] ${message}`, ...args);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
error(message, ...args) {
|
|
141
|
+
if (this.enabled && console.error) {
|
|
142
|
+
console.error(`[GetuAI Error] ${message}`, ...args);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Get user agent info
|
|
147
|
+
export function getUserAgent() {
|
|
148
|
+
return navigator.userAgent || "";
|
|
149
|
+
}
|
|
150
|
+
// Get referrer
|
|
151
|
+
export function getReferrer() {
|
|
152
|
+
return document.referrer || "";
|
|
153
|
+
}
|
|
154
|
+
// Get current URL
|
|
155
|
+
export function getCurrentUrl() {
|
|
156
|
+
return window.location.href;
|
|
157
|
+
}
|
|
158
|
+
// Get page title
|
|
159
|
+
export function getPageTitle() {
|
|
160
|
+
return document.title || "";
|
|
161
|
+
}
|
|
162
|
+
// Check if user is online
|
|
163
|
+
export function isOnline() {
|
|
164
|
+
return navigator.onLine;
|
|
165
|
+
}
|
|
166
|
+
// Generate session ID
|
|
167
|
+
export function generateSessionId() {
|
|
168
|
+
return `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
169
|
+
}
|
|
170
|
+
// Validate email format
|
|
171
|
+
export function isValidEmail(email) {
|
|
172
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
173
|
+
return emailRegex.test(email);
|
|
174
|
+
}
|
|
175
|
+
// Format currency
|
|
176
|
+
export function formatCurrency(amount, currency = "USD") {
|
|
177
|
+
return new Intl.NumberFormat("en-US", {
|
|
178
|
+
style: "currency",
|
|
179
|
+
currency: currency,
|
|
180
|
+
}).format(amount);
|
|
181
|
+
}
|
|
182
|
+
// Add UTM parameters to URL
|
|
183
|
+
export function addUTMToURL(url, utmParams) {
|
|
184
|
+
try {
|
|
185
|
+
const urlObj = new URL(url);
|
|
186
|
+
// Add UTM parameters if they don't already exist
|
|
187
|
+
Object.entries(utmParams).forEach(([key, value]) => {
|
|
188
|
+
if (value && !urlObj.searchParams.has(key)) {
|
|
189
|
+
urlObj.searchParams.set(key, value);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
return urlObj.toString();
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
// If URL parsing fails, return original URL
|
|
196
|
+
return url;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// Check if domain should be excluded from UTM passing
|
|
200
|
+
export function shouldExcludeDomain(url, excludeDomains = []) {
|
|
201
|
+
try {
|
|
202
|
+
const urlObj = new URL(url);
|
|
203
|
+
const hostname = urlObj.hostname.toLowerCase();
|
|
204
|
+
return excludeDomains.some((domain) => {
|
|
205
|
+
const excludeDomain = domain.toLowerCase();
|
|
206
|
+
return (hostname === excludeDomain || hostname.endsWith(`.${excludeDomain}`));
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
// Get domain from URL
|
|
214
|
+
export function getDomainFromURL(url) {
|
|
215
|
+
try {
|
|
216
|
+
const urlObj = new URL(url);
|
|
217
|
+
return urlObj.hostname;
|
|
218
|
+
}
|
|
219
|
+
catch (error) {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
// Check if URL is external (different domain)
|
|
224
|
+
export function isExternalURL(url) {
|
|
225
|
+
try {
|
|
226
|
+
const urlObj = new URL(url);
|
|
227
|
+
const currentDomain = window.location.hostname;
|
|
228
|
+
return urlObj.hostname !== currentDomain;
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
// Filter UTM parameters based on configuration
|
|
235
|
+
export function filterUTMParams(utmData, allowedParams = ["utm_source", "utm_medium", "utm_campaign"]) {
|
|
236
|
+
const filtered = {};
|
|
237
|
+
allowedParams.forEach((param) => {
|
|
238
|
+
if (utmData[param]) {
|
|
239
|
+
filtered[param] = utmData[param];
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
return filtered;
|
|
243
|
+
}
|
|
244
|
+
// Get query string from URL
|
|
245
|
+
export function getQueryString(url) {
|
|
246
|
+
try {
|
|
247
|
+
const targetUrl = url || window.location.href;
|
|
248
|
+
const urlObj = new URL(targetUrl);
|
|
249
|
+
return urlObj.search;
|
|
250
|
+
}
|
|
251
|
+
catch (error) {
|
|
252
|
+
return "";
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
// Get query parameters as object
|
|
256
|
+
export function getQueryParams(url) {
|
|
257
|
+
try {
|
|
258
|
+
const targetUrl = url || window.location.href;
|
|
259
|
+
const urlObj = new URL(targetUrl);
|
|
260
|
+
const params = {};
|
|
261
|
+
urlObj.searchParams.forEach((value, key) => {
|
|
262
|
+
params[key] = value;
|
|
263
|
+
});
|
|
264
|
+
return params;
|
|
265
|
+
}
|
|
266
|
+
catch (error) {
|
|
267
|
+
return {};
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
// Clean URL by removing UTM parameters
|
|
271
|
+
export function cleanURL() {
|
|
272
|
+
try {
|
|
273
|
+
const currentUrl = new URL(window.location.href);
|
|
274
|
+
const utmKeys = [
|
|
275
|
+
"utm_source",
|
|
276
|
+
"utm_medium",
|
|
277
|
+
"utm_campaign",
|
|
278
|
+
"utm_term",
|
|
279
|
+
"utm_content",
|
|
280
|
+
];
|
|
281
|
+
let hasParams = false;
|
|
282
|
+
utmKeys.forEach((key) => {
|
|
283
|
+
if (currentUrl.searchParams.has(key)) {
|
|
284
|
+
currentUrl.searchParams.delete(key);
|
|
285
|
+
hasParams = true;
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
if (hasParams) {
|
|
289
|
+
// Use replaceState to avoid page reload and history entry
|
|
290
|
+
window.history.replaceState({}, document.title, currentUrl.toString());
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
catch (error) {
|
|
294
|
+
// Handle invalid URLs silently
|
|
295
|
+
console.warn("Failed to clean URL:", error);
|
|
296
|
+
}
|
|
297
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "getu-attribution-v2-sdk",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "GetuAI Attribution SDK for client-side tracking",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.esm.js",
|
|
7
|
+
"browser": "dist/getuai-attribution.min.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.esm.js",
|
|
12
|
+
"require": "./dist/index.js",
|
|
13
|
+
"types": "./dist/index.d.ts"
|
|
14
|
+
},
|
|
15
|
+
"./browser": {
|
|
16
|
+
"import": "./dist/getuai-attribution.min.js",
|
|
17
|
+
"require": "./dist/getuai-attribution.min.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "npm run clean && tsc && webpack --mode production && npm run build:esm",
|
|
22
|
+
"build:dev": "npm run clean && tsc && webpack --mode development && npm run build:esm",
|
|
23
|
+
"build:esm": "rollup -c",
|
|
24
|
+
"dev": "webpack --mode development --watch",
|
|
25
|
+
"test": "jest",
|
|
26
|
+
"lint": "eslint src/**/*.ts",
|
|
27
|
+
"clean": "rimraf dist",
|
|
28
|
+
"prepublishOnly": "npm run build"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"attribution",
|
|
32
|
+
"tracking",
|
|
33
|
+
"analytics",
|
|
34
|
+
"utm",
|
|
35
|
+
"conversion"
|
|
36
|
+
],
|
|
37
|
+
"author": "GetuAI",
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/jest": "^29.5.0",
|
|
41
|
+
"@typescript-eslint/eslint-plugin": "^5.59.0",
|
|
42
|
+
"@typescript-eslint/parser": "^5.59.0",
|
|
43
|
+
"eslint": "^8.38.0",
|
|
44
|
+
"jest": "^29.5.0",
|
|
45
|
+
"rimraf": "^5.0.0",
|
|
46
|
+
"rollup": "^3.28.0",
|
|
47
|
+
"@rollup/plugin-typescript": "^11.1.0",
|
|
48
|
+
"@rollup/plugin-commonjs": "^25.0.0",
|
|
49
|
+
"@rollup/plugin-node-resolve": "^15.0.0",
|
|
50
|
+
"ts-jest": "^29.1.0",
|
|
51
|
+
"ts-loader": "^9.4.0",
|
|
52
|
+
"typescript": "^5.0.0",
|
|
53
|
+
"webpack": "^5.88.0",
|
|
54
|
+
"webpack-cli": "^5.1.0"
|
|
55
|
+
},
|
|
56
|
+
"files": [
|
|
57
|
+
"dist",
|
|
58
|
+
"example-script.html"
|
|
59
|
+
],
|
|
60
|
+
"publishConfig": {
|
|
61
|
+
"access": "public"
|
|
62
|
+
}
|
|
63
|
+
}
|