@umituz/web-traffic 1.0.11 → 1.0.13
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/package.json +1 -1
- package/src/domains/affiliate/repositories/affiliate.repository.interface.ts +3 -2
- package/src/domains/conversion/aggregates/order.aggregate.ts +4 -2
- package/src/domains/conversion/index.ts +0 -3
- package/src/domains/tracking/aggregates/session.aggregate.ts +4 -16
- package/src/domains/tracking/index.ts +0 -4
- package/src/domains/tracking/repositories/event.repository.interface.ts +7 -6
- package/src/infrastructure/tracking/web-traffic.service.ts +6 -2
- package/src/presentation/context.tsx +5 -5
- package/src/domains/conversion/events/conversion-recorded.domain-event.ts +0 -30
- package/src/domains/tracking/events/event-tracked.domain-event.ts +0 -28
- package/src/domains/tracking/events/pageview-tracked.domain-event.ts +0 -31
package/package.json
CHANGED
|
@@ -8,6 +8,7 @@ import type { AffiliateVisit } from '../entities/affiliate-visit.entity';
|
|
|
8
8
|
import type { AffiliateId } from '../value-objects/affiliate-id.vo';
|
|
9
9
|
import type { SiteId } from '../value-objects/site-id.vo';
|
|
10
10
|
import type { SessionId } from '../../tracking/value-objects/session-id.vo';
|
|
11
|
+
import type { EventId } from '../../tracking/value-objects/event-id.vo';
|
|
11
12
|
|
|
12
13
|
export interface IAffiliateRepository {
|
|
13
14
|
save(affiliate: Affiliate): Promise<void>;
|
|
@@ -19,8 +20,8 @@ export interface IAffiliateRepository {
|
|
|
19
20
|
|
|
20
21
|
export interface IAffiliateVisitRepository {
|
|
21
22
|
save(visit: AffiliateVisit): Promise<void>;
|
|
22
|
-
findById(id:
|
|
23
|
+
findById(id: EventId): Promise<AffiliateVisit | null>;
|
|
23
24
|
findByAffiliate(affiliateId: AffiliateId): Promise<AffiliateVisit[]>;
|
|
24
25
|
findByVisitorAndSession(visitorId: string, sessionId: SessionId): Promise<AffiliateVisit[]>;
|
|
25
|
-
delete(id:
|
|
26
|
+
delete(id: EventId): Promise<void>;
|
|
26
27
|
}
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
* @description Manages conversion order and its items
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import type { OrderItem } from '../entities/order-item.entity';
|
|
6
|
+
import type { OrderItem, OrderItemCreateInput } from '../entities/order-item.entity';
|
|
7
7
|
import type { EventId } from '../../tracking/value-objects/event-id.vo';
|
|
8
8
|
import { Money } from '../value-objects/money.vo';
|
|
9
|
+
import { createOrderItem } from '../entities/order-item.entity';
|
|
9
10
|
|
|
10
11
|
export interface OrderCreateInput {
|
|
11
12
|
sessionId: string;
|
|
@@ -37,12 +38,13 @@ export class Order {
|
|
|
37
38
|
// Calculate total and create items
|
|
38
39
|
let totalAmount = 0;
|
|
39
40
|
for (const item of input.items) {
|
|
40
|
-
const
|
|
41
|
+
const createInput: OrderItemCreateInput = {
|
|
41
42
|
id: item.id,
|
|
42
43
|
name: item.name,
|
|
43
44
|
price: item.price,
|
|
44
45
|
quantity: item.quantity,
|
|
45
46
|
};
|
|
47
|
+
const orderItem = createOrderItem(createInput);
|
|
46
48
|
this.items.push(orderItem);
|
|
47
49
|
totalAmount += item.price * item.quantity;
|
|
48
50
|
}
|
|
@@ -16,6 +16,3 @@ export { Money } from './value-objects/money.vo';
|
|
|
16
16
|
|
|
17
17
|
// Repository Interfaces
|
|
18
18
|
export type { IConversionRepository } from './repositories/conversion.repository.interface';
|
|
19
|
-
|
|
20
|
-
// Domain Events
|
|
21
|
-
export { ConversionRecorded } from './events/conversion-recorded.domain-event';
|
|
@@ -25,8 +25,6 @@ export class Session {
|
|
|
25
25
|
private endTime: number | null;
|
|
26
26
|
private events: Event[];
|
|
27
27
|
private pageviews: Pageview[];
|
|
28
|
-
private eventCount: number;
|
|
29
|
-
private pageviewCount: number;
|
|
30
28
|
private entryPage: string | null;
|
|
31
29
|
private exitPage: string | null;
|
|
32
30
|
|
|
@@ -39,8 +37,6 @@ export class Session {
|
|
|
39
37
|
this.endTime = null;
|
|
40
38
|
this.events = [];
|
|
41
39
|
this.pageviews = [];
|
|
42
|
-
this.eventCount = 0;
|
|
43
|
-
this.pageviewCount = 0;
|
|
44
40
|
this.entryPage = null;
|
|
45
41
|
this.exitPage = null;
|
|
46
42
|
Object.freeze(this.id);
|
|
@@ -56,8 +52,6 @@ export class Session {
|
|
|
56
52
|
throw new Error('Cannot add event to expired session');
|
|
57
53
|
}
|
|
58
54
|
this.events.push(event);
|
|
59
|
-
this.eventCount++;
|
|
60
|
-
this.updateLastActivity();
|
|
61
55
|
}
|
|
62
56
|
|
|
63
57
|
addPageview(pageview: Pageview): void {
|
|
@@ -65,12 +59,10 @@ export class Session {
|
|
|
65
59
|
throw new Error('Cannot add pageview to expired session');
|
|
66
60
|
}
|
|
67
61
|
this.pageviews.push(pageview);
|
|
68
|
-
this.pageviewCount++;
|
|
69
62
|
this.exitPage = pageview.path;
|
|
70
63
|
if (!this.entryPage) {
|
|
71
64
|
this.entryPage = pageview.path;
|
|
72
65
|
}
|
|
73
|
-
this.updateLastActivity();
|
|
74
66
|
}
|
|
75
67
|
|
|
76
68
|
getEntryPage(): string | null {
|
|
@@ -117,11 +109,11 @@ export class Session {
|
|
|
117
109
|
}
|
|
118
110
|
|
|
119
111
|
getEventCount(): number {
|
|
120
|
-
return this.
|
|
112
|
+
return this.events.length;
|
|
121
113
|
}
|
|
122
114
|
|
|
123
115
|
getPageviewCount(): number {
|
|
124
|
-
return this.
|
|
116
|
+
return this.pageviews.length;
|
|
125
117
|
}
|
|
126
118
|
|
|
127
119
|
getEvents(): Event[] {
|
|
@@ -132,10 +124,6 @@ export class Session {
|
|
|
132
124
|
return [...this.pageviews];
|
|
133
125
|
}
|
|
134
126
|
|
|
135
|
-
private updateLastActivity(): void {
|
|
136
|
-
// Could emit domain event here
|
|
137
|
-
}
|
|
138
|
-
|
|
139
127
|
toJSON() {
|
|
140
128
|
return {
|
|
141
129
|
id: this.id.toString(),
|
|
@@ -144,8 +132,8 @@ export class Session {
|
|
|
144
132
|
deviceInfo: this.deviceInfo.toJSON(),
|
|
145
133
|
startTime: this.startTime,
|
|
146
134
|
endTime: this.endTime,
|
|
147
|
-
eventCount: this.
|
|
148
|
-
pageviewCount: this.
|
|
135
|
+
eventCount: this.events.length,
|
|
136
|
+
pageviewCount: this.pageviews.length,
|
|
149
137
|
entryPage: this.entryPage,
|
|
150
138
|
exitPage: this.exitPage,
|
|
151
139
|
duration: this.getDuration(),
|
|
@@ -28,10 +28,6 @@ export type {
|
|
|
28
28
|
ISessionRepository,
|
|
29
29
|
} from './repositories/event.repository.interface';
|
|
30
30
|
|
|
31
|
-
// Domain Events
|
|
32
|
-
export { EventTracked } from './events/event-tracked.domain-event';
|
|
33
|
-
export { PageviewTracked } from './events/pageview-tracked.domain-event';
|
|
34
|
-
|
|
35
31
|
// Application Services
|
|
36
32
|
export { TrackingCommandService } from './application/tracking-command.service';
|
|
37
33
|
export type { TrackingCommandResult } from './application/tracking-command.service';
|
|
@@ -7,6 +7,7 @@ import type { Event } from '../entities/event.entity';
|
|
|
7
7
|
import type { Pageview } from '../entities/pageview.entity';
|
|
8
8
|
import type { EventId } from '../value-objects/event-id.vo';
|
|
9
9
|
import type { SessionId } from '../value-objects/session-id.vo';
|
|
10
|
+
import type { Session } from '../aggregates/session.aggregate';
|
|
10
11
|
|
|
11
12
|
export interface IEventRepository {
|
|
12
13
|
save(event: Event | Pageview): Promise<void>;
|
|
@@ -16,15 +17,15 @@ export interface IEventRepository {
|
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
export interface IPageviewRepository {
|
|
19
|
-
save(pageview:
|
|
20
|
-
findById(id: EventId): Promise<
|
|
21
|
-
findBySessionId(sessionId: SessionId): Promise<
|
|
20
|
+
save(pageview: Pageview): Promise<void>;
|
|
21
|
+
findById(id: EventId): Promise<Pageview | null>;
|
|
22
|
+
findBySessionId(sessionId: SessionId): Promise<Pageview[]>;
|
|
22
23
|
delete(id: EventId): Promise<void>;
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
export interface ISessionRepository {
|
|
26
|
-
save(session:
|
|
27
|
-
findById(id: SessionId): Promise<
|
|
28
|
-
findActive(deviceId: string, timeoutMs: number): Promise<
|
|
27
|
+
save(session: Session): Promise<void>;
|
|
28
|
+
findById(id: SessionId): Promise<Session | null>;
|
|
29
|
+
findActive(deviceId: string, timeoutMs: number): Promise<Session | null>;
|
|
29
30
|
delete(id: SessionId): Promise<void>;
|
|
30
31
|
}
|
|
@@ -179,12 +179,16 @@ class WebTrafficService {
|
|
|
179
179
|
this.originalReplaceState = history.replaceState;
|
|
180
180
|
|
|
181
181
|
history.pushState = (...args) => {
|
|
182
|
-
this.originalPushState
|
|
182
|
+
if (this.originalPushState) {
|
|
183
|
+
this.originalPushState.apply(history, args);
|
|
184
|
+
}
|
|
183
185
|
void this.trackPageView();
|
|
184
186
|
};
|
|
185
187
|
|
|
186
188
|
history.replaceState = (...args) => {
|
|
187
|
-
this.originalReplaceState
|
|
189
|
+
if (this.originalReplaceState) {
|
|
190
|
+
this.originalReplaceState.apply(history, args);
|
|
191
|
+
}
|
|
188
192
|
void this.trackPageView();
|
|
189
193
|
};
|
|
190
194
|
|
|
@@ -8,7 +8,7 @@ import { webTrafficService, type WebTrafficConfig } from '../infrastructure/trac
|
|
|
8
8
|
import type { WebTrafficContextValue } from './hooks';
|
|
9
9
|
import type { TrackingCommandResult } from '../domains/tracking/application/tracking-command.service';
|
|
10
10
|
|
|
11
|
-
const
|
|
11
|
+
const WebTrafficContext = createContext<WebTrafficContextValue | null>(null);
|
|
12
12
|
|
|
13
13
|
export interface WebTrafficProviderProps {
|
|
14
14
|
readonly children: ReactNode;
|
|
@@ -26,10 +26,10 @@ export function WebTrafficProvider({ children, config }: WebTrafficProviderProps
|
|
|
26
26
|
|
|
27
27
|
const value = useMemo<WebTrafficContextValue>(
|
|
28
28
|
() => ({
|
|
29
|
-
trackEvent:
|
|
29
|
+
trackEvent: (name: string, properties?: Record<string, unknown>) => {
|
|
30
30
|
return webTrafficService.trackEvent(name, properties);
|
|
31
31
|
},
|
|
32
|
-
trackPageView:
|
|
32
|
+
trackPageView: (path?: string) => {
|
|
33
33
|
return webTrafficService.trackPageView(path);
|
|
34
34
|
},
|
|
35
35
|
isInitialized: webTrafficService.isInitialized(),
|
|
@@ -38,7 +38,7 @@ export function WebTrafficProvider({ children, config }: WebTrafficProviderProps
|
|
|
38
38
|
[config]
|
|
39
39
|
);
|
|
40
40
|
|
|
41
|
-
return <
|
|
41
|
+
return <WebTrafficContext.Provider value={value}>{children}</WebTrafficContext.Provider>;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
export {
|
|
44
|
+
export { WebTrafficContext };
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Conversion Recorded Domain Event
|
|
3
|
-
* @description Published when a conversion is recorded
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { Money } from '../value-objects/money.vo';
|
|
7
|
-
|
|
8
|
-
export class ConversionRecorded {
|
|
9
|
-
readonly eventType = 'ConversionRecorded';
|
|
10
|
-
readonly orderId: string;
|
|
11
|
-
readonly sessionId: string;
|
|
12
|
-
readonly revenue: Money;
|
|
13
|
-
readonly itemCount: number;
|
|
14
|
-
readonly occurredAt: number;
|
|
15
|
-
|
|
16
|
-
constructor(params: {
|
|
17
|
-
orderId: string;
|
|
18
|
-
sessionId: string;
|
|
19
|
-
revenue: Money;
|
|
20
|
-
itemCount: number;
|
|
21
|
-
occurredAt?: number;
|
|
22
|
-
}) {
|
|
23
|
-
this.orderId = params.orderId;
|
|
24
|
-
this.sessionId = params.sessionId;
|
|
25
|
-
this.revenue = params.revenue;
|
|
26
|
-
this.itemCount = params.itemCount;
|
|
27
|
-
this.occurredAt = params.occurredAt ?? Date.now();
|
|
28
|
-
Object.freeze(this);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Event Tracked Domain Event
|
|
3
|
-
* @description Published when an analytics event is tracked
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { EventId } from '../../tracking/value-objects/event-id.vo';
|
|
7
|
-
import type { SessionId } from '../../tracking/value-objects/session-id.vo';
|
|
8
|
-
|
|
9
|
-
export class EventTracked {
|
|
10
|
-
readonly eventType = 'EventTracked';
|
|
11
|
-
readonly eventId: EventId;
|
|
12
|
-
readonly sessionId: SessionId;
|
|
13
|
-
readonly eventName: string;
|
|
14
|
-
readonly occurredAt: number;
|
|
15
|
-
|
|
16
|
-
constructor(params: {
|
|
17
|
-
eventId: EventId;
|
|
18
|
-
sessionId: SessionId;
|
|
19
|
-
eventName: string;
|
|
20
|
-
occurredAt?: number;
|
|
21
|
-
}) {
|
|
22
|
-
this.eventId = params.eventId;
|
|
23
|
-
this.sessionId = params.sessionId;
|
|
24
|
-
this.eventName = params.eventName;
|
|
25
|
-
this.occurredAt = params.occurredAt ?? Date.now();
|
|
26
|
-
Object.freeze(this);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pageview Tracked Domain Event
|
|
3
|
-
* @description Published when a pageview is tracked
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { EventId } from '../../tracking/value-objects/event-id.vo';
|
|
7
|
-
import type { SessionId } from '../../tracking/value-objects/session-id.vo';
|
|
8
|
-
|
|
9
|
-
export class PageviewTracked {
|
|
10
|
-
readonly eventType = 'PageviewTracked';
|
|
11
|
-
readonly pageviewId: EventId;
|
|
12
|
-
readonly sessionId: SessionId;
|
|
13
|
-
readonly path: string;
|
|
14
|
-
readonly hasUTM: boolean;
|
|
15
|
-
readonly occurredAt: number;
|
|
16
|
-
|
|
17
|
-
constructor(params: {
|
|
18
|
-
pageviewId: EventId;
|
|
19
|
-
sessionId: SessionId;
|
|
20
|
-
path: string;
|
|
21
|
-
hasUTM: boolean;
|
|
22
|
-
occurredAt?: number;
|
|
23
|
-
}) {
|
|
24
|
-
this.pageviewId = params.pageviewId;
|
|
25
|
-
this.sessionId = params.sessionId;
|
|
26
|
-
this.path = params.path;
|
|
27
|
-
this.hasUTM = params.hasUTM;
|
|
28
|
-
this.occurredAt = params.occurredAt ?? Date.now();
|
|
29
|
-
Object.freeze(this);
|
|
30
|
-
}
|
|
31
|
-
}
|