-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathseries.js
141 lines (129 loc) · 5.37 KB
/
series.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
* Copyright 2024 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
import { reclassifyAcquisition } from './utils.js';
/**
* @module series
* @description This module provides a list of standardized series for use in analyzing web
* experiences.
* each series can be registered with a name using `DataChunks.addSeries(name, series)`.
*/
/**
* @typedef {import('./distiller.js').Bundle} Bundle
*/
/**
* A page view is an impression of a page. At this moment, pre-rendering is also
* considered a page view.
* @param {Bundle} bundle a series of events that belong to the same page view
* @returns {number} the number of page views
*/
export const pageViews = (bundle) => bundle.weight;
/**
* A visit is a page view that does not follow an internal link. This means a visit starts
* when users follow an external link or enter the URL in the browser.
* @param {Bundle} bundle a series of events that belong to the same page view
* @returns {number} the number of visits
*/
export const visits = (bundle) => (bundle.visit ? bundle.weight : 0);
/**
* A bounce is a visit that does not have any click events.
* @param {Bundle} bundle a series of events that belong to the same page view
* @returns {number} the number of bounces
*/
export const bounces = (bundle) => (bundle.visit && !bundle.events.find(({ checkpoint }) => checkpoint === 'click')
? bundle.weight
: 0);
/**
* The largest contentful paint is the time it takes for the largest contentful element to load.
* @param {Bundle} bundle a series of events that belong to the same page view
* @returns {number} the largest contentful paint
*/
export const lcp = (bundle) => bundle.cwvLCP;
/**
* The cumulative layout shift is the sum of all layout shifts in a page view.
* @param {Bundle} bundle a series of events that belong to the same page view
* @returns {number} the cumulative layout shift
*/
export const cls = (bundle) => bundle.cwvCLS;
/**
* The interaction to next paint is the time it takes for the next paint after an interaction.
* @param {Bundle} bundle a series of events that belong to the same page view
* @returns {number} the interaction to next paint
*/
export const inp = (bundle) => bundle.cwvINP;
/**
* The time to first byte is the time it takes for the first byte to arrive.
* @param {Bundle} bundle a series of events that belong to the same page view
*/
export const ttfb = (bundle) => bundle.cwvTTFB;
/**
* A page view is considered engaged if there has been at least some user interaction
* or significant content has been viewed, i.e. 4 or more viewmedia or viewblock events.
* @param {Bundle} bundle a series of events that belong to the same page view
* @returns {number} the number of engaged page views
*/
export const engagement = (bundle) => {
const clickEngagement = bundle.events.filter((evt) => evt.checkpoint === 'click').length > 0
? bundle.weight
: 0;
const contentEngagement = bundle.events
.filter((evt) => evt.checkpoint === 'viewmedia' || evt.checkpoint === 'viewblock')
.length > 3
? bundle.weight
: 0;
return clickEngagement || contentEngagement;
};
/**
* The number of earned visits is the number of visits that are not paid or owned.
* @param {Bundle} bundle a series of events that belong to the same page view
* @returns {number} the number of earned conversions
*/
export const earned = (bundle) => {
const reclassified = bundle.events.map(reclassifyAcquisition);
if (!reclassified.find((evt) => evt.checkpoint === 'enter')) {
// we only consider enter events
return 0;
}
if (!reclassified.find((evt) => evt.checkpoint === 'acquisition')) {
// this is fully organic, as there are no traces of any acquisition
return bundle.weight;
}
if (reclassified.find((evt) => evt.checkpoint === 'acquisition' && evt.source.startsWith('paid'))) {
// this is paid, as there is at least one paid acquisition
return 0;
}
if (reclassified.find((evt) => evt.checkpoint === 'acquisition' && evt.source.startsWith('owned'))) {
// owned does not count as earned
return 0;
}
return bundle.weight;
};
/**
* The number of organic visits is the number of visits that are not paid.
* @param {Bundle} bundle a series of events that belong to the same page view
* @returns {number} the number of earned conversions
*/
export const organic = (bundle) => {
const reclassified = bundle.events.map(reclassifyAcquisition);
if (!reclassified.find((evt) => evt.checkpoint === 'enter')) {
// we only consider enter events
return 0;
}
if (!reclassified.find((evt) => evt.checkpoint === 'acquisition')) {
// this is fully organic, as there are no traces of any acquisition
return bundle.weight;
}
if (reclassified.find((evt) => evt.checkpoint === 'acquisition' && evt.source.startsWith('paid'))) {
// this is paid, as there is at least one paid acquisition
return 0;
}
return bundle.weight;
};