userpath-js 0.0.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/dist/pixel.js +1 -0
- package/examples/usage.ts +83 -0
- package/package.json +17 -0
- package/src/clients/api.ts +92 -0
- package/src/clients/events.ts +55 -0
- package/src/clients/identity.ts +54 -0
- package/src/clients/session.ts +47 -0
- package/src/index.ts +72 -0
- package/src/pixel.ts +28 -0
- package/src/schemas/config.ts +4 -0
- package/src/schemas/events.ts +31 -0
- package/src/schemas/identity.ts +6 -0
package/dist/pixel.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
class n{namespace;constructor({namespace:r}){this.namespace=r}getItem(r){let t=localStorage.getItem(`${this.namespace}.${r}`)||"";try{return JSON.parse(t)}catch(e){return null}}setItem(r,t){localStorage.setItem(`${this.namespace}.${r}`,JSON.stringify(t))}removeItem(r){localStorage.removeItem(`${this.namespace}.${r}`)}}var u=new n({namespace:"userpath"});class c{baseUrl;siteId;queue=[];flushInterval=null;constructor(r){this.baseUrl=r.baseUrl||"",this.siteId=r.siteId,this.flushInterval=window.setInterval(()=>this.flush(),5000)}track(r){if(this.queue.push(r),this.queue.length>=10)this.flush()}flush(){if(this.queue.length===0)return;let r=[...this.queue];this.queue=[],fetch(`${this.baseUrl}/events`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({siteId:this.siteId,sessionId:this.getSessionId(),timestamp:new Date().toISOString(),userAgent:navigator.userAgent,screenWidth:window.screen.width,screenHeight:window.screen.height,language:navigator.language,timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,events:r}),keepalive:!0}).catch((t)=>{this.queue=[...r,...this.queue].slice(0,100),console.error("Error sending analytics data:",t)})}getSessionId(){let r=u.getItem("session_id");if(!r)r=this.generateId(),u.setItem("session_id",r);return r}generateId(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(r){let t=Math.random()*16|0;return(r==="x"?t:t&3|8).toString(16)})}}class o{api;constructor(r){this.api=r}trackPageView(){let r={type:"pageview",url:window.location.href,referrer:document.referrer,title:document.title};this.api.track(r)}trackCustomEvent(r,t={}){let e={type:"event",name:r,properties:t};this.api.track(e)}trackPurchase(r){let t={type:"purchase",...r};this.api.track(t)}}class g{api;anonymousId=null;currentUser=null;constructor(r){this.api=r;this.anonymousId=this.getStoredAnonymousId()}getAnonymousId(){if(!this.anonymousId)this.anonymousId=this.api.generateId(),localStorage.setItem("up_anonymous_id",this.anonymousId);return this.anonymousId}getUserId(){return this.currentUser?.userId||null}identify(r){this.currentUser=r,this.api.track({type:"identify",anonymousId:this.getAnonymousId(),...r})}getStoredAnonymousId(){return localStorage.getItem("up_anonymous_id")}}class p{api;events;constructor(r){this.api=r;this.events=new o(r),this.initialize()}initialize(){this.events.trackPageView(),this.setupHistoryChange()}setupHistoryChange(){let{pushState:r,replaceState:t}=history;history.pushState=(...e)=>{r.apply(history,e),this.events.trackPageView()},history.replaceState=(...e)=>{t.apply(history,e),this.events.trackPageView()},window.addEventListener("popstate",()=>{this.events.trackPageView()})}}class m{events;session;identity;constructor(r){let t=new c(r);this.events=new o(t),this.session=new p(t),this.identity=new g(t)}getAnonymousId(){return this.identity.getAnonymousId()}getUserId(){return this.identity.getUserId()}identify(r){this.identity.identify(r)}trackPageView(){this.events.trackPageView()}trackEvent(r,t={}){this.events.trackCustomEvent(r,t)}trackPurchase(r){this.events.trackPurchase(r)}}var w=typeof window!=="undefined";document.addEventListener("DOMContentLoaded",()=>{if(!w)return;try{let r=document.querySelector("[data-up]").getAttribute("data-up")||"",t=document.querySelector("[data-up]").getAttribute("src")||"",a=new URL(t).origin+"/v1",d=new m({siteId:r,baseUrl:a});window.userpath=d,setTimeout(()=>{console.log(r,a,d)},1000)}catch(r){console.error(r)}});
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// Example code showing how the client SDK should handle user identity resolution
|
|
2
|
+
|
|
3
|
+
import { UserPath } from '../src';
|
|
4
|
+
|
|
5
|
+
// Initialize the tracking SDK
|
|
6
|
+
const userpath = new UserPath({
|
|
7
|
+
siteId: 'site_123', // Required
|
|
8
|
+
baseUrl: 'https://api.userpath.to/v1', // Optional
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
// When a user first visits the site, they get an anonymous ID
|
|
12
|
+
// This is stored in local storage
|
|
13
|
+
const anonymousId = userpath.getAnonymousId();
|
|
14
|
+
console.log('Anonymous visitor ID:', anonymousId);
|
|
15
|
+
|
|
16
|
+
// Example: Track a page view (this is done automatically on initialization)
|
|
17
|
+
// But you can also track it manually if needed
|
|
18
|
+
userpath.trackPageView();
|
|
19
|
+
|
|
20
|
+
// Example: Track a custom event (like clicking the purchase button)
|
|
21
|
+
function onPurchaseButtonClick() {
|
|
22
|
+
userpath.trackEvent('click_purchase', {
|
|
23
|
+
buttonId: 'purchase-btn',
|
|
24
|
+
plan: 'premium',
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Example: When user identifies themselves (e.g., signs up or logs in)
|
|
29
|
+
function onUserIdentified(user: { id: string; email: string; name: string }) {
|
|
30
|
+
// Identify the user and connect them to their anonymous activity
|
|
31
|
+
userpath.identify({
|
|
32
|
+
userId: user.id,
|
|
33
|
+
email: user.email,
|
|
34
|
+
name: user.name,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
console.log('User identified:', userpath.getUserId());
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Example: Track a purchase event
|
|
41
|
+
function trackPurchase(purchaseDetails: {
|
|
42
|
+
productId: string;
|
|
43
|
+
price: number;
|
|
44
|
+
currency: string;
|
|
45
|
+
plan: string;
|
|
46
|
+
couponApplied?: string;
|
|
47
|
+
}) {
|
|
48
|
+
userpath.trackPurchase({
|
|
49
|
+
productId: purchaseDetails.productId,
|
|
50
|
+
price: purchaseDetails.price,
|
|
51
|
+
currency: purchaseDetails.currency,
|
|
52
|
+
properties: {
|
|
53
|
+
plan: purchaseDetails.plan,
|
|
54
|
+
couponApplied: purchaseDetails.couponApplied,
|
|
55
|
+
// Include user identification if available
|
|
56
|
+
userId: userpath.getUserId(),
|
|
57
|
+
anonymousId: userpath.getAnonymousId(),
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Example usage flow:
|
|
63
|
+
|
|
64
|
+
// 1. SDK is initialized and first pageview is tracked automatically
|
|
65
|
+
|
|
66
|
+
// 2. User clicks purchase button while still anonymous
|
|
67
|
+
onPurchaseButtonClick();
|
|
68
|
+
|
|
69
|
+
// 3. User signs up or logs in
|
|
70
|
+
onUserIdentified({
|
|
71
|
+
id: 'user_123',
|
|
72
|
+
email: 'john@example.com',
|
|
73
|
+
name: 'John Doe',
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// 4. User completes a purchase (now as an identified user)
|
|
77
|
+
trackPurchase({
|
|
78
|
+
productId: 'plan_premium',
|
|
79
|
+
price: 1337,
|
|
80
|
+
currency: 'USD',
|
|
81
|
+
plan: 'Premium Annual',
|
|
82
|
+
couponApplied: 'WELCOME20',
|
|
83
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "userpath-js",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"main": "dist/pixel.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "bun build src/index.ts --outdir ./dist --watch",
|
|
8
|
+
"build": "bun build src/index.ts --outdir ./dist --minify",
|
|
9
|
+
"build.pixel": "bun build src/pixel.ts --outdir ./dist",
|
|
10
|
+
"build.pixel.prod": "bun build src/pixel.ts --outdir ./dist --minify",
|
|
11
|
+
"prepublish": "bun run build.pixel.prod"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"bun-types": "latest",
|
|
15
|
+
"typescript": "^5.0.0"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { memory } from '@userpath/core/browser';
|
|
2
|
+
|
|
3
|
+
import { Config } from '../schemas/config';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Base API client for UserPath SDK
|
|
7
|
+
*/
|
|
8
|
+
export class ApiClient {
|
|
9
|
+
protected baseUrl: string;
|
|
10
|
+
protected siteId: string;
|
|
11
|
+
protected queue: any[] = [];
|
|
12
|
+
protected flushInterval: number | null = null;
|
|
13
|
+
|
|
14
|
+
constructor(config: Config) {
|
|
15
|
+
this.baseUrl = config.baseUrl || '';
|
|
16
|
+
this.siteId = config.siteId;
|
|
17
|
+
|
|
18
|
+
// Set up automatic flushing
|
|
19
|
+
this.flushInterval = window.setInterval(() => this.flush(), 5000);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Add an event to the queue and flush if needed
|
|
24
|
+
*/
|
|
25
|
+
public track(event: any): void {
|
|
26
|
+
this.queue.push(event);
|
|
27
|
+
|
|
28
|
+
if (this.queue.length >= 10) {
|
|
29
|
+
this.flush();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Flush queued events to the server
|
|
35
|
+
*/
|
|
36
|
+
protected flush(): void {
|
|
37
|
+
if (this.queue.length === 0) return;
|
|
38
|
+
|
|
39
|
+
const eventsToSend = [...this.queue];
|
|
40
|
+
this.queue = [];
|
|
41
|
+
|
|
42
|
+
fetch(`${this.baseUrl}/events`, {
|
|
43
|
+
method: 'POST',
|
|
44
|
+
headers: {
|
|
45
|
+
'Content-Type': 'application/json',
|
|
46
|
+
},
|
|
47
|
+
body: JSON.stringify({
|
|
48
|
+
siteId: this.siteId,
|
|
49
|
+
sessionId: this.getSessionId(),
|
|
50
|
+
timestamp: new Date().toISOString(),
|
|
51
|
+
userAgent: navigator.userAgent,
|
|
52
|
+
screenWidth: window.screen.width,
|
|
53
|
+
screenHeight: window.screen.height,
|
|
54
|
+
language: navigator.language,
|
|
55
|
+
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
56
|
+
events: eventsToSend,
|
|
57
|
+
}),
|
|
58
|
+
// Use beacon API for more reliable delivery
|
|
59
|
+
keepalive: true,
|
|
60
|
+
}).catch((error) => {
|
|
61
|
+
// If sending fails, add back to queue for retry
|
|
62
|
+
this.queue = [...eventsToSend, ...this.queue].slice(0, 100);
|
|
63
|
+
console.error('Error sending analytics data:', error);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Get or generate a session ID
|
|
69
|
+
*/
|
|
70
|
+
protected getSessionId(): string {
|
|
71
|
+
let sessionId = memory.getItem<string>('session_id');
|
|
72
|
+
if (!sessionId) {
|
|
73
|
+
sessionId = this.generateId();
|
|
74
|
+
memory.setItem('session_id', sessionId);
|
|
75
|
+
}
|
|
76
|
+
return sessionId;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Generate a UUID v4
|
|
81
|
+
*/
|
|
82
|
+
public generateId(): string {
|
|
83
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(
|
|
84
|
+
/[xy]/g,
|
|
85
|
+
function (c) {
|
|
86
|
+
const r = (Math.random() * 16) | 0;
|
|
87
|
+
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
88
|
+
return v.toString(16);
|
|
89
|
+
}
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { ApiClient } from './api';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Events client for handling different types of tracking events
|
|
5
|
+
*/
|
|
6
|
+
export class EventsClient {
|
|
7
|
+
constructor(private api: ApiClient) {}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Track a page view event
|
|
11
|
+
*/
|
|
12
|
+
public trackPageView(): void {
|
|
13
|
+
const event = {
|
|
14
|
+
type: 'pageview',
|
|
15
|
+
url: window.location.href,
|
|
16
|
+
referrer: document.referrer,
|
|
17
|
+
title: document.title,
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
this.api.track(event);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Track a custom event
|
|
25
|
+
*/
|
|
26
|
+
public trackCustomEvent(
|
|
27
|
+
name: string,
|
|
28
|
+
properties: Record<string, any> = {}
|
|
29
|
+
): void {
|
|
30
|
+
const event = {
|
|
31
|
+
type: 'event',
|
|
32
|
+
name,
|
|
33
|
+
properties,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
this.api.track(event);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Track a purchase event
|
|
41
|
+
*/
|
|
42
|
+
public trackPurchase(params: {
|
|
43
|
+
productId: string;
|
|
44
|
+
price: number;
|
|
45
|
+
currency: string;
|
|
46
|
+
properties?: Record<string, any>;
|
|
47
|
+
}): void {
|
|
48
|
+
const event = {
|
|
49
|
+
type: 'purchase',
|
|
50
|
+
...params,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
this.api.track(event);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { UserIdentity } from '../schemas/identity';
|
|
2
|
+
import { ApiClient } from './api';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Identity client for managing user identification
|
|
6
|
+
*/
|
|
7
|
+
export class IdentityClient {
|
|
8
|
+
private anonymousId: string | null = null;
|
|
9
|
+
private currentUser: UserIdentity | null = null;
|
|
10
|
+
|
|
11
|
+
constructor(private api: ApiClient) {
|
|
12
|
+
this.anonymousId = this.getStoredAnonymousId();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Get the anonymous ID for the current visitor
|
|
17
|
+
*/
|
|
18
|
+
public getAnonymousId(): string {
|
|
19
|
+
if (!this.anonymousId) {
|
|
20
|
+
this.anonymousId = this.api.generateId();
|
|
21
|
+
localStorage.setItem('up_anonymous_id', this.anonymousId);
|
|
22
|
+
}
|
|
23
|
+
return this.anonymousId;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Get the current identified user's ID if available
|
|
28
|
+
*/
|
|
29
|
+
public getUserId(): string | null {
|
|
30
|
+
return this.currentUser?.userId || null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Identify a user and associate them with their anonymous ID
|
|
35
|
+
*/
|
|
36
|
+
public identify(identity: UserIdentity): void {
|
|
37
|
+
// Store the current user
|
|
38
|
+
this.currentUser = identity;
|
|
39
|
+
|
|
40
|
+
// Track the identity mapping
|
|
41
|
+
this.api.track({
|
|
42
|
+
type: 'identify',
|
|
43
|
+
anonymousId: this.getAnonymousId(),
|
|
44
|
+
...identity,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Get the stored anonymous ID if it exists
|
|
50
|
+
*/
|
|
51
|
+
private getStoredAnonymousId(): string | null {
|
|
52
|
+
return localStorage.getItem('up_anonymous_id');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ApiClient } from './api';
|
|
2
|
+
import { EventsClient } from './events';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Session client for managing user sessions and automatic tracking
|
|
6
|
+
*/
|
|
7
|
+
export class SessionClient {
|
|
8
|
+
private events: EventsClient;
|
|
9
|
+
|
|
10
|
+
constructor(private api: ApiClient) {
|
|
11
|
+
this.events = new EventsClient(api);
|
|
12
|
+
this.initialize();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Initialize session tracking
|
|
17
|
+
*/
|
|
18
|
+
private initialize(): void {
|
|
19
|
+
// Track initial pageview
|
|
20
|
+
this.events.trackPageView();
|
|
21
|
+
|
|
22
|
+
// Set up history change tracking
|
|
23
|
+
this.setupHistoryChange();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Set up tracking for history/navigation changes
|
|
28
|
+
*/
|
|
29
|
+
private setupHistoryChange(): void {
|
|
30
|
+
const originalPushState = history.pushState;
|
|
31
|
+
const originalReplaceState = history.replaceState;
|
|
32
|
+
|
|
33
|
+
history.pushState = (...args) => {
|
|
34
|
+
originalPushState.apply(history, args);
|
|
35
|
+
this.events.trackPageView();
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
history.replaceState = (...args) => {
|
|
39
|
+
originalReplaceState.apply(history, args);
|
|
40
|
+
this.events.trackPageView();
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
window.addEventListener('popstate', () => {
|
|
44
|
+
this.events.trackPageView();
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { ApiClient } from './clients/api';
|
|
2
|
+
import { EventsClient } from './clients/events';
|
|
3
|
+
import { IdentityClient } from './clients/identity';
|
|
4
|
+
import { SessionClient } from './clients/session';
|
|
5
|
+
import { Config } from './schemas/config';
|
|
6
|
+
import { UserIdentity } from './schemas/identity';
|
|
7
|
+
|
|
8
|
+
export class UserPath {
|
|
9
|
+
private events: EventsClient;
|
|
10
|
+
private session: SessionClient;
|
|
11
|
+
private identity: IdentityClient;
|
|
12
|
+
|
|
13
|
+
constructor(config: Config) {
|
|
14
|
+
// Initialize clients
|
|
15
|
+
const baseClient = new ApiClient(config);
|
|
16
|
+
this.events = new EventsClient(baseClient);
|
|
17
|
+
this.session = new SessionClient(baseClient);
|
|
18
|
+
this.identity = new IdentityClient(baseClient);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Get the anonymous ID for the current visitor
|
|
23
|
+
*/
|
|
24
|
+
public getAnonymousId(): string {
|
|
25
|
+
return this.identity.getAnonymousId();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Get the current identified user's ID if available
|
|
30
|
+
*/
|
|
31
|
+
public getUserId(): string | null {
|
|
32
|
+
return this.identity.getUserId();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Identify a user
|
|
37
|
+
*/
|
|
38
|
+
public identify(identity: UserIdentity): void {
|
|
39
|
+
this.identity.identify(identity);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Track a page view event
|
|
44
|
+
*/
|
|
45
|
+
public trackPageView(): void {
|
|
46
|
+
this.events.trackPageView();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Track a custom event
|
|
51
|
+
*/
|
|
52
|
+
public trackEvent(name: string, properties: Record<string, any> = {}): void {
|
|
53
|
+
this.events.trackCustomEvent(name, properties);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Track a purchase event
|
|
58
|
+
*/
|
|
59
|
+
public trackPurchase(params: {
|
|
60
|
+
productId: string;
|
|
61
|
+
price: number;
|
|
62
|
+
currency: string;
|
|
63
|
+
properties?: Record<string, any>;
|
|
64
|
+
}): void {
|
|
65
|
+
this.events.trackPurchase(params);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Export types
|
|
70
|
+
export * from './schemas/events';
|
|
71
|
+
export * from './schemas/config';
|
|
72
|
+
export * from './schemas/identity';
|
package/src/pixel.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { UserPath } from './index';
|
|
2
|
+
|
|
3
|
+
const isBrowser = typeof window !== 'undefined';
|
|
4
|
+
|
|
5
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
6
|
+
if (!isBrowser) return;
|
|
7
|
+
try {
|
|
8
|
+
const siteId =
|
|
9
|
+
document!.querySelector('[data-up]')!.getAttribute('data-up') || '';
|
|
10
|
+
const src = document!.querySelector('[data-up]')!.getAttribute('src') || '';
|
|
11
|
+
const url = new URL(src);
|
|
12
|
+
const baseUrl = url.origin + '/v1';
|
|
13
|
+
|
|
14
|
+
const userpath = new UserPath({
|
|
15
|
+
siteId,
|
|
16
|
+
baseUrl,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// @ts-ignore
|
|
20
|
+
window.userpath = userpath;
|
|
21
|
+
|
|
22
|
+
setTimeout(() => {
|
|
23
|
+
console.log(siteId, baseUrl, userpath);
|
|
24
|
+
}, 1000);
|
|
25
|
+
} catch (err) {
|
|
26
|
+
console.error(err);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface PageViewEvent {
|
|
2
|
+
type: 'pageview';
|
|
3
|
+
url: string;
|
|
4
|
+
referrer: string;
|
|
5
|
+
title: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface CustomEvent {
|
|
9
|
+
type: 'event';
|
|
10
|
+
name: string;
|
|
11
|
+
properties: Record<string, any>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface PurchaseEvent {
|
|
15
|
+
type: 'purchase';
|
|
16
|
+
productId: string;
|
|
17
|
+
price: number;
|
|
18
|
+
currency: string;
|
|
19
|
+
properties?: Record<string, any>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface IdentifyEvent {
|
|
23
|
+
type: 'identify';
|
|
24
|
+
anonymousId: string;
|
|
25
|
+
userId: string;
|
|
26
|
+
email?: string;
|
|
27
|
+
name?: string;
|
|
28
|
+
properties?: Record<string, any>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export type Event = PageViewEvent | CustomEvent | PurchaseEvent | IdentifyEvent;
|