Skip to content

Commit 1038980

Browse files
zhu-xiaoweixiaoweii
andauthored
feat: optimize page view after session start (#44)
Co-authored-by: xiaoweii <xiaoweii@amazom.com>
1 parent 86cd73b commit 1038980

16 files changed

+159
-28
lines changed

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@
1919
"lint": "npx eslint src",
2020
"test": "npm run prebuild && npx jest -w 1 --coverage",
2121
"clean": "rimraf lib-esm lib dist",
22-
"pack": "npm run build && npm pack",
23-
"publish": "npm run pack && npm publish"
22+
"pack": "npm run build && npm pack"
2423
},
2524
"repository": {
2625
"type": "git",

src/browser/BrowserInfo.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Logger } from '@aws-amplify/core';
2+
import { StorageUtil } from '../util/StorageUtil';
23

34
/**
45
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
@@ -84,7 +85,7 @@ export class BrowserInfo {
8485
const performanceEntries = performance.getEntriesByType('navigation');
8586
if (performanceEntries && performanceEntries.length > 0) {
8687
const type = (performanceEntries[0] as any)['type'];
87-
return type === 'reload';
88+
return type === 'reload' && StorageUtil.getPreviousPageUrl() !== '';
8889
}
8990
} else {
9091
logger.warn('unsupported web environment for performance');

src/tracker/PageViewTracker.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,20 @@ export class PageViewTracker extends BaseTracker {
2525
searchKeywords = Event.Constants.KEYWORDS;
2626
lastEngageTime = 0;
2727
lastScreenStartTimestamp = 0;
28+
isFirstTime = true;
2829

2930
init() {
3031
const configuredSearchKeywords = this.provider.configuration.searchKeyWords;
3132
Object.assign(this.searchKeywords, configuredSearchKeywords);
3233
this.onPageChange = this.onPageChange.bind(this);
33-
if (this.context.configuration.pageType === PageType.SPA) {
34-
this.trackPageViewForSPA();
35-
} else {
34+
if (this.isMultiPageApp()) {
3635
if (!BrowserInfo.isFromReload()) {
3736
this.onPageChange();
3837
}
38+
} else {
39+
this.trackPageViewForSPA();
3940
}
41+
this.isFirstTime = false;
4042
}
4143

4244
trackPageViewForSPA() {
@@ -55,11 +57,17 @@ export class PageViewTracker extends BaseTracker {
5557
const currentPageUrl = BrowserInfo.getCurrentPageUrl();
5658
const currentPageTitle = BrowserInfo.getCurrentPageTitle();
5759
if (
60+
this.isFirstTime ||
61+
this.isMultiPageApp() ||
5862
previousPageUrl !== currentPageUrl ||
5963
previousPageTitle !== currentPageTitle
6064
) {
6165
this.provider.scrollTracker?.enterNewPage();
62-
if (previousPageUrl !== '') {
66+
if (
67+
!this.isMultiPageApp() &&
68+
!this.isFirstTime &&
69+
previousPageUrl !== ''
70+
) {
6371
this.recordUserEngagement();
6472
}
6573
this.trackPageView(previousPageUrl, previousPageTitle);
@@ -128,6 +136,10 @@ export class PageViewTracker extends BaseTracker {
128136
return new Date().getTime() - this.lastScreenStartTimestamp;
129137
}
130138

139+
isMultiPageApp() {
140+
return this.context.configuration.pageType === PageType.multiPageApp;
141+
}
142+
131143
trackSearchEvents() {
132144
if (!this.context.configuration.isTrackSearchEvents) return;
133145
const searchStr = window.location.search;

src/tracker/SessionTracker.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ export class SessionTracker extends BaseTracker {
5252

5353
handleInit() {
5454
this.session = Session.getCurrentSession(this.context);
55-
StorageUtil.clearPageInfo();
5655
if (StorageUtil.getIsFirstOpen()) {
5756
this.provider.record({
5857
name: Event.PresetEvent.FIRST_OPEN,
@@ -69,7 +68,11 @@ export class SessionTracker extends BaseTracker {
6968
this.session = Session.getCurrentSession(this.context);
7069
if (this.session.isNewSession()) {
7170
pageViewTracker.setIsEntrances();
71+
StorageUtil.clearPageInfo();
7272
this.provider.record({ name: Event.PresetEvent.SESSION_START });
73+
if (!isFirstTime) {
74+
pageViewTracker.onPageChange();
75+
}
7376
}
7477
if (!this.provider.configuration.isTrackAppStartEvents) return;
7578
if (isFirstTime && this.isFromCurrentHost()) return;
@@ -89,6 +92,7 @@ export class SessionTracker extends BaseTracker {
8992
onPageHide() {
9093
logger.debug('page hide');
9194
this.storeSession();
95+
StorageUtil.checkClickstreamId();
9296
const isImmediate = !(this.isWindowClosing && BrowserInfo.isFirefox());
9397
this.recordUserEngagement(isImmediate);
9498
this.recordAppEnd(isImmediate);

src/util/StorageUtil.ts

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,28 +39,39 @@ export class StorageUtil {
3939
static readonly previousPageStartTimeKey =
4040
this.prefix + 'previousPageStartTimeKey';
4141
static readonly userIdMappingKey = this.prefix + 'userIdMappingKey';
42+
private static deviceId = '';
43+
private static userUniqueId = '';
4244

4345
static getDeviceId(): string {
44-
let deviceId = localStorage.getItem(StorageUtil.deviceIdKey) ?? '';
45-
if (deviceId === '') {
46+
if (StorageUtil.deviceId !== '') {
47+
return StorageUtil.deviceId;
48+
}
49+
let deviceId = localStorage.getItem(StorageUtil.deviceIdKey);
50+
if (deviceId === null) {
4651
deviceId = uuidV4();
4752
localStorage.setItem(StorageUtil.deviceIdKey, deviceId);
4853
}
54+
StorageUtil.deviceId = deviceId;
4955
return deviceId;
5056
}
5157

5258
static setCurrentUserUniqueId(userUniqueId: string) {
59+
StorageUtil.userUniqueId = userUniqueId;
5360
localStorage.setItem(StorageUtil.userUniqueIdKey, userUniqueId);
5461
}
5562

5663
static getCurrentUserUniqueId(): string {
57-
let userUniqueId = localStorage.getItem(StorageUtil.userUniqueIdKey) ?? '';
58-
if (userUniqueId === '') {
64+
if (StorageUtil.userUniqueId !== '') {
65+
return StorageUtil.userUniqueId;
66+
}
67+
let userUniqueId = localStorage.getItem(StorageUtil.userUniqueIdKey);
68+
if (userUniqueId === null) {
5969
userUniqueId = uuidV4();
6070
StorageUtil.setCurrentUserUniqueId(userUniqueId);
6171
localStorage.setItem(StorageUtil.userUniqueIdKey, userUniqueId);
6272
StorageUtil.saveUserFirstTouchTimestamp();
6373
}
74+
StorageUtil.userUniqueId = userUniqueId;
6475
return userUniqueId;
6576
}
6677

@@ -293,4 +304,40 @@ export class StorageUtil {
293304
timestamp.toString()
294305
);
295306
}
307+
308+
static checkDeviceId() {
309+
const currentDeviceId = localStorage.getItem(StorageUtil.deviceIdKey) ?? '';
310+
if (StorageUtil.deviceId !== '' && currentDeviceId === '') {
311+
localStorage.setItem(StorageUtil.deviceIdKey, StorageUtil.deviceId);
312+
}
313+
}
314+
315+
static checkUserUniqueId() {
316+
const currentUserUniqueId =
317+
localStorage.getItem(StorageUtil.userUniqueIdKey) ?? '';
318+
if (StorageUtil.userUniqueId !== '' && currentUserUniqueId === '') {
319+
localStorage.setItem(
320+
StorageUtil.userUniqueIdKey,
321+
StorageUtil.userUniqueId
322+
);
323+
}
324+
}
325+
326+
static checkIsFirstOpen() {
327+
if (StorageUtil.getIsFirstOpen()) {
328+
StorageUtil.saveIsFirstOpenToFalse();
329+
}
330+
}
331+
332+
static checkClickstreamId() {
333+
StorageUtil.checkDeviceId();
334+
StorageUtil.checkUserUniqueId();
335+
StorageUtil.checkIsFirstOpen();
336+
}
337+
338+
static clearAll() {
339+
localStorage.clear();
340+
(StorageUtil as any).deviceid = '';
341+
(StorageUtil as any).userUniqueId = '';
342+
}
296343
}

test/ClickstreamAnalytics.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { StorageUtil } from '../src/util/StorageUtil';
1818

1919
describe('ClickstreamAnalytics test', () => {
2020
beforeEach(() => {
21-
localStorage.clear();
21+
StorageUtil.clearAll();
2222
const mockSendRequestSuccess = jest.fn().mockResolvedValue(true);
2323
jest
2424
.spyOn(NetRequest, 'sendRequest')

test/browser/BrowserInfo.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@
1313
import { setPerformanceEntries } from './BrowserUtil';
1414
import { MockObserver } from './MockObserver';
1515
import { BrowserInfo } from '../../src/browser';
16+
import { StorageUtil } from '../../src/util/StorageUtil';
1617

1718
describe('BrowserInfo test', () => {
1819
afterEach(() => {
1920
jest.clearAllMocks();
2021
jest.resetAllMocks();
2122
});
2223
test('test create BrowserInfo', () => {
24+
StorageUtil.clearAllEvents()
2325
const referrer = 'https://example.com/collect';
2426
Object.defineProperty(window.document, 'referrer', {
2527
writable: true,
@@ -109,6 +111,7 @@ describe('BrowserInfo test', () => {
109111
test('test web page not from reload', () => {
110112
(global as any).PerformanceObserver = MockObserver;
111113
setPerformanceEntries(true, true);
114+
StorageUtil.savePreviousPageUrl("http://localhost:8080")
112115
expect(BrowserInfo.isFromReload()).toBeTruthy();
113116
});
114117
});

test/provider/BatchModeTimer.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,13 @@
1313
import { SendMode } from '../../src';
1414
import { NetRequest } from '../../src/network/NetRequest';
1515
import { ClickstreamProvider } from '../../src/provider';
16+
import { StorageUtil } from '../../src/util/StorageUtil';
1617
import { setUpBrowserPerformance } from '../browser/BrowserUtil';
1718

1819
describe('ClickstreamProvider timer test', () => {
1920
let provider: ClickstreamProvider;
2021
beforeEach(() => {
21-
localStorage.clear();
22+
StorageUtil.clearAll();
2223
setUpBrowserPerformance();
2324
provider = new ClickstreamProvider();
2425
const mockSendRequest = jest.fn().mockResolvedValue(true);

test/provider/ClickstreamProvider.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ describe('ClickstreamProvider test', () => {
3232
let mockRecordProfileSet: any;
3333

3434
beforeEach(async () => {
35-
localStorage.clear();
35+
StorageUtil.clearAll();
3636
setUpBrowserPerformance();
3737
const mockSendRequest = jest.fn().mockResolvedValue(true);
3838
jest.spyOn(NetRequest, 'sendRequest').mockImplementation(mockSendRequest);

test/provider/EventRecorder.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ describe('EventRecorder test', () => {
2626
let eventRecorder: EventRecorder;
2727
let context: ClickstreamContext;
2828
beforeEach(() => {
29-
localStorage.clear();
29+
StorageUtil.clearAll()
3030
context = new ClickstreamContext(new BrowserInfo(), {
3131
appId: 'testApp',
3232
endpoint: 'https://localhost:8080/collect',

0 commit comments

Comments
 (0)