-
Notifications
You must be signed in to change notification settings - Fork 30
/
generic.ts
165 lines (142 loc) · 4.99 KB
/
generic.ts
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
import { name as packageName, version } from '../package.json';
import { initQueue } from './queue';
import type {
AllowedPropertyValues,
AnalyticsProps,
FlagsDataInput,
BeforeSend,
BeforeSendEvent,
} from './types';
import {
isBrowser,
parseProperties,
setMode,
isDevelopment,
isProduction,
computeRoute,
} from './utils';
export const DEV_SCRIPT_URL =
'https://va.vercel-scripts.com/v1/script.debug.js';
export const PROD_SCRIPT_URL = '/_vercel/insights/script.js';
export const basepathVariableName = 'NEXT_PUBLIC_WEB_ANALYTICS_BASEPATH';
/**
* Injects the Vercel Web Analytics script into the page head and starts tracking page views. Read more in our [documentation](https://vercel.com/docs/concepts/analytics/package).
* @param [props] - Analytics options.
* @param [props.mode] - The mode to use for the analytics script. Defaults to `auto`.
* - `auto` - Automatically detect the environment. Uses `production` if the environment cannot be determined.
* - `production` - Always use the production script. (Sends events to the server)
* - `development` - Always use the development script. (Logs events to the console)
* @param [props.debug] - Whether to enable debug logging in development. Defaults to `true`.
* @param [props.beforeSend] - A middleware function to modify events before they are sent. Should return the event object or `null` to cancel the event.
* @param [props.dsn] - The DSN of the project to send events to. Only required when self-hosting.
* @param [props.disableAutoTrack] - Whether the injected script should track page views from pushState events. Disable if route is updated after pushState, a manually call page pageview().
*/
function inject(
props: AnalyticsProps & {
framework?: string;
disableAutoTrack?: boolean;
} = {
debug: true,
}
): void {
if (!isBrowser()) return;
setMode(props.mode);
initQueue();
if (props.beforeSend) {
window.va?.('beforeSend', props.beforeSend);
}
const src =
props.scriptSrc || (isDevelopment() ? DEV_SCRIPT_URL : PROD_SCRIPT_URL);
if (document.head.querySelector(`script[src*="${src}"]`)) return;
const script = document.createElement('script');
script.src = src;
script.defer = true;
script.dataset.sdkn =
packageName + (props.framework ? `/${props.framework}` : '');
script.dataset.sdkv = version;
if (props.disableAutoTrack) {
script.dataset.disableAutoTrack = '1';
}
if (props.endpoint) {
script.dataset.endpoint = props.endpoint;
} else if (process.env[basepathVariableName]) {
script.dataset.endpoint = `/${process.env[basepathVariableName]}/_vercel/insights`;
}
if (props.dsn) {
script.dataset.dsn = props.dsn;
}
script.onerror = (): void => {
const errorMessage = isDevelopment()
? 'Please check if any ad blockers are enabled and try again.'
: 'Be sure to enable Web Analytics for your project and deploy again. See https://vercel.com/docs/analytics/quickstart for more information.';
// eslint-disable-next-line no-console -- Logging to console is intentional
console.log(
`[Vercel Web Analytics] Failed to load script from ${src}. ${errorMessage}`
);
};
if (isDevelopment() && props.debug === false) {
script.dataset.debug = 'false';
}
document.head.appendChild(script);
}
/**
* Tracks a custom event. Please refer to the [documentation](https://vercel.com/docs/concepts/analytics/custom-events) for more information on custom events.
* @param name - The name of the event.
* * Examples: `Purchase`, `Click Button`, or `Play Video`.
* @param [properties] - Additional properties of the event. Nested objects are not supported. Allowed values are `string`, `number`, `boolean`, and `null`.
*/
function track(
name: string,
properties?: Record<string, AllowedPropertyValues>,
options?: {
flags?: FlagsDataInput;
}
): void {
if (!isBrowser()) {
const msg =
'[Vercel Web Analytics] Please import `track` from `@vercel/analytics/server` when using this function in a server environment';
if (isProduction()) {
// eslint-disable-next-line no-console -- Show warning in production
console.warn(msg);
} else {
throw new Error(msg);
}
return;
}
if (!properties) {
window.va?.('event', { name, options });
return;
}
try {
const props = parseProperties(properties, {
strip: isProduction(),
});
window.va?.('event', {
name,
data: props,
options,
});
} catch (err) {
if (err instanceof Error && isDevelopment()) {
// eslint-disable-next-line no-console -- Logging to console is intentional
console.error(err);
}
}
}
function pageview({
route,
path,
}: {
route?: string | null;
path?: string;
}): void {
window.va?.('pageview', { route, path });
}
export { inject, track, pageview, computeRoute };
export type { AnalyticsProps, BeforeSend, BeforeSendEvent };
// eslint-disable-next-line import/no-default-export -- Default export is intentional
export default {
inject,
track,
computeRoute,
};