@hellyeah/x-ray 0.1.0-beta.5

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.
@@ -0,0 +1,476 @@
1
+ // src/constants.ts
2
+ var cv = {
3
+ purchase: "cv_purchase",
4
+ subscribe: "cv_subscribe",
5
+ startTrial: "cv_start_trial",
6
+ leadSubmit: "cv_lead_submit",
7
+ registrationComplete: "cv_registration_complete",
8
+ bookAppointment: "cv_book_appointment",
9
+ contact: "cv_contact",
10
+ submitApplication: "cv_submit_application",
11
+ addToCart: "cv_add_to_cart",
12
+ beginCheckout: "cv_begin_checkout",
13
+ addPaymentInfo: "cv_add_payment_info",
14
+ viewContent: "cv_view_content",
15
+ search: "cv_search"
16
+ };
17
+ // src/server/types.ts
18
+ var isUnrefable = (value) => typeof value === "object" && value !== null && ("unref" in value);
19
+
20
+ // src/server/index.ts
21
+ var DEFAULTS = {
22
+ flushAt: 20,
23
+ flushInterval: 1e4,
24
+ maxQueueSize: 1000,
25
+ requestTimeout: 1e4,
26
+ retryDelay: 3000
27
+ };
28
+ var PROPERTY_LIMITS = {
29
+ maxProperties: 20,
30
+ maxKeyLength: 100,
31
+ maxStringValueLength: 500
32
+ };
33
+ var FLAT_TYPES = new Set(["string", "number", "boolean"]);
34
+ var RETRY_ATTEMPTS = 3;
35
+ var REVENUE_WARNING_THRESHOLD = 1e4;
36
+ var CURRENCY_PATTERN = /^[A-Z]{3}$/;
37
+ var TRAILING_SLASH = /\/$/;
38
+ var SERVERLESS_ENV_KEYS = [
39
+ "VERCEL",
40
+ "AWS_LAMBDA_FUNCTION_NAME",
41
+ "NETLIFY",
42
+ "CLOUDFLARE_WORKER"
43
+ ];
44
+ var DATA_KEYS = ["currency", "tag", "url", "hostname"];
45
+ var ATTRIBUTION_KEYS = [
46
+ "utm_source",
47
+ "utm_medium",
48
+ "utm_campaign",
49
+ "utm_content",
50
+ "utm_term",
51
+ "gclid",
52
+ "fbclid",
53
+ "msclkid",
54
+ "ttclid",
55
+ "li_fat_id",
56
+ "twclid"
57
+ ];
58
+ var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
59
+ var WELL_KNOWN_CONTEXT_SYMBOLS = [
60
+ Symbol.for("@vercel/request-context"),
61
+ Symbol.for("@next/request-context")
62
+ ];
63
+ var discoverWaitUntil = () => {
64
+ const g = globalThis;
65
+ for (const sym of WELL_KNOWN_CONTEXT_SYMBOLS) {
66
+ const waitUntil = g[sym]?.get?.()?.waitUntil;
67
+ if (waitUntil)
68
+ return waitUntil;
69
+ }
70
+ return null;
71
+ };
72
+
73
+ class XRay {
74
+ queue = [];
75
+ timer = null;
76
+ defaultDistinctId;
77
+ logFn;
78
+ flushing = false;
79
+ fetchFn;
80
+ shutdownCalled = false;
81
+ cfg;
82
+ constructor(websiteId, options) {
83
+ const resolvedWebsiteId = websiteId ?? process.env.XRAY_WEBSITE_ID ?? "";
84
+ const resolvedHost = options?.host ?? process.env.XRAY_HOST ?? "https://xray-staging.hellyeahai.com";
85
+ if (!resolvedWebsiteId) {
86
+ console.warn("[x-ray] websiteId is missing. Pass it to the constructor or set XRAY_WEBSITE_ID env var.");
87
+ }
88
+ this.cfg = {
89
+ websiteId: resolvedWebsiteId,
90
+ host: resolvedHost.replace(TRAILING_SLASH, ""),
91
+ flushAt: options?.flushAt ?? DEFAULTS.flushAt,
92
+ flushInterval: options?.flushInterval ?? DEFAULTS.flushInterval,
93
+ maxQueueSize: options?.maxQueueSize ?? DEFAULTS.maxQueueSize,
94
+ requestTimeout: options?.requestTimeout ?? DEFAULTS.requestTimeout,
95
+ disabled: options?.disabled ?? false,
96
+ retryDelay: options?.retryDelay ?? DEFAULTS.retryDelay,
97
+ context: options?.context ?? {},
98
+ waitUntil: options?.waitUntil ?? null
99
+ };
100
+ this.fetchFn = options?.fetch ?? globalThis.fetch;
101
+ this.logFn = options?.logger ?? null;
102
+ if (!this.cfg.disabled) {
103
+ this.timer = setInterval(() => {
104
+ const p = this.flush().catch(() => {});
105
+ const wU = this.resolveWaitUntil();
106
+ if (wU)
107
+ wU(p);
108
+ }, this.cfg.flushInterval);
109
+ if (isUnrefable(this.timer)) {
110
+ this.timer.unref();
111
+ }
112
+ if (!(this.cfg.waitUntil || discoverWaitUntil())) {
113
+ const isServerless = SERVERLESS_ENV_KEYS.some((k) => typeof process !== "undefined" && (k in process.env));
114
+ if (isServerless) {
115
+ this.log({
116
+ action: "serverless_detect",
117
+ outcome: "warning",
118
+ message: "Serverless environment detected without waitUntil — batched track() events may be lost. Pass waitUntil in options or use trackImmediate()."
119
+ });
120
+ }
121
+ }
122
+ }
123
+ }
124
+ track(event, data) {
125
+ try {
126
+ if (this.cfg.disabled) {
127
+ return;
128
+ }
129
+ const distinctId = data?.distinctId ?? this.defaultDistinctId;
130
+ if (!(event && distinctId)) {
131
+ this.log({
132
+ action: "track",
133
+ outcome: "drop",
134
+ message: "missing event name or distinctId",
135
+ event: event || undefined
136
+ });
137
+ return;
138
+ }
139
+ const item = this.buildItem(event, distinctId, data);
140
+ this.enqueue(item);
141
+ this.log({
142
+ action: "track",
143
+ outcome: "success",
144
+ message: "queued",
145
+ event
146
+ });
147
+ } catch (err) {
148
+ this.log({
149
+ action: "track",
150
+ outcome: "error",
151
+ message: "track error",
152
+ error: err
153
+ });
154
+ }
155
+ }
156
+ async trackImmediate(event, data) {
157
+ try {
158
+ if (this.cfg.disabled) {
159
+ return;
160
+ }
161
+ const distinctId = data?.distinctId ?? this.defaultDistinctId;
162
+ if (!(event && distinctId)) {
163
+ this.log({
164
+ action: "track_immediate",
165
+ outcome: "drop",
166
+ message: "missing event name or distinctId",
167
+ event: event || undefined
168
+ });
169
+ return;
170
+ }
171
+ const item = this.buildItem(event, distinctId, data);
172
+ await this.sendBatch([item]);
173
+ this.log({
174
+ action: "track_immediate",
175
+ outcome: "success",
176
+ message: "sent immediate",
177
+ event
178
+ });
179
+ } catch (err) {
180
+ this.log({
181
+ action: "track_immediate",
182
+ outcome: "error",
183
+ message: "trackImmediate error",
184
+ error: err
185
+ });
186
+ }
187
+ }
188
+ identify(params) {
189
+ try {
190
+ this.defaultDistinctId = params.distinctId;
191
+ this.log({
192
+ action: "identify",
193
+ outcome: "success",
194
+ message: "identified"
195
+ });
196
+ } catch (err) {
197
+ this.log({
198
+ action: "identify",
199
+ outcome: "error",
200
+ message: "identify error",
201
+ error: err
202
+ });
203
+ }
204
+ }
205
+ async flush() {
206
+ try {
207
+ if (this.cfg.disabled)
208
+ return;
209
+ if (this.flushing || this.queue.length === 0)
210
+ return;
211
+ this.flushing = true;
212
+ while (this.queue.length > 0) {
213
+ const items = this.queue.splice(0, this.cfg.flushAt);
214
+ try {
215
+ await this.sendBatch(items);
216
+ this.log({
217
+ action: "flush",
218
+ outcome: "success",
219
+ message: "flushed",
220
+ count: items.length
221
+ });
222
+ } catch (err) {
223
+ this.queue.unshift(...items);
224
+ this.log({
225
+ action: "flush",
226
+ outcome: "error",
227
+ message: "re-queued events after send failure",
228
+ count: items.length,
229
+ error: err
230
+ });
231
+ break;
232
+ }
233
+ }
234
+ this.flushing = false;
235
+ } catch (err) {
236
+ this.flushing = false;
237
+ this.log({
238
+ action: "flush",
239
+ outcome: "error",
240
+ message: "flush error",
241
+ error: err
242
+ });
243
+ }
244
+ }
245
+ async shutdown(timeoutMs = 5000) {
246
+ try {
247
+ if (this.shutdownCalled) {
248
+ return;
249
+ }
250
+ this.shutdownCalled = true;
251
+ if (this.timer) {
252
+ clearInterval(this.timer);
253
+ this.timer = null;
254
+ }
255
+ await Promise.race([this.flush(), sleep(timeoutMs)]);
256
+ this.log({
257
+ action: "shutdown",
258
+ outcome: "success",
259
+ message: "shutdown complete"
260
+ });
261
+ } catch (err) {
262
+ this.log({
263
+ action: "shutdown",
264
+ outcome: "error",
265
+ message: "shutdown error",
266
+ error: err
267
+ });
268
+ }
269
+ }
270
+ debug(enabled) {
271
+ if (enabled) {
272
+ this.logFn = (entry) => console.log("[x-ray]", JSON.stringify(entry));
273
+ } else {
274
+ this.logFn = null;
275
+ }
276
+ }
277
+ enqueue(item) {
278
+ if (this.queue.length >= this.cfg.maxQueueSize) {
279
+ this.queue.shift();
280
+ this.log({
281
+ action: "enqueue",
282
+ outcome: "overflow",
283
+ message: "queue full, dropped oldest event",
284
+ count: this.queue.length
285
+ });
286
+ }
287
+ this.queue.push(item);
288
+ if (this.queue.length >= this.cfg.flushAt) {
289
+ const trigger = () => {
290
+ const p = this.flush().catch(() => {});
291
+ const wU = this.resolveWaitUntil();
292
+ if (wU)
293
+ wU(p);
294
+ };
295
+ queueMicrotask(trigger);
296
+ }
297
+ }
298
+ async sendBatch(items) {
299
+ const payload = items.map((item) => ({
300
+ type: "event",
301
+ payload: item
302
+ }));
303
+ for (let attempt = 0;attempt < RETRY_ATTEMPTS; attempt++) {
304
+ const controller = new AbortController;
305
+ const timeout = setTimeout(() => controller.abort(), this.cfg.requestTimeout);
306
+ if (isUnrefable(timeout))
307
+ timeout.unref();
308
+ try {
309
+ const res = await this.fetchFn(`${this.cfg.host}/api/batch`, {
310
+ method: "POST",
311
+ headers: {
312
+ "Content-Type": "application/json",
313
+ "X-HY-Source": "server-sdk"
314
+ },
315
+ body: JSON.stringify(payload),
316
+ signal: controller.signal
317
+ });
318
+ clearTimeout(timeout);
319
+ if (res.ok) {
320
+ return;
321
+ }
322
+ if (res.status >= 500) {
323
+ this.log({
324
+ action: "send_batch",
325
+ outcome: "retry",
326
+ message: "server error, retrying",
327
+ statusCode: res.status,
328
+ attempt: attempt + 1,
329
+ maxAttempts: RETRY_ATTEMPTS
330
+ });
331
+ if (attempt < RETRY_ATTEMPTS - 1) {
332
+ await sleep(this.cfg.retryDelay);
333
+ continue;
334
+ }
335
+ this.log({
336
+ action: "send_batch",
337
+ outcome: "drop",
338
+ message: "dropping batch after retries exhausted",
339
+ statusCode: res.status,
340
+ attempt: attempt + 1,
341
+ maxAttempts: RETRY_ATTEMPTS
342
+ });
343
+ return;
344
+ }
345
+ this.log({
346
+ action: "send_batch",
347
+ outcome: "drop",
348
+ message: "client error, dropping batch",
349
+ statusCode: res.status
350
+ });
351
+ return;
352
+ } catch (err) {
353
+ clearTimeout(timeout);
354
+ if (attempt < RETRY_ATTEMPTS - 1 && !controller.signal.aborted) {
355
+ this.log({
356
+ action: "send_batch",
357
+ outcome: "retry",
358
+ message: "network error, retrying",
359
+ attempt: attempt + 1,
360
+ maxAttempts: RETRY_ATTEMPTS,
361
+ error: err
362
+ });
363
+ await sleep(this.cfg.retryDelay);
364
+ continue;
365
+ }
366
+ this.log({
367
+ action: "send_batch",
368
+ outcome: "drop",
369
+ message: "dropping batch",
370
+ error: err
371
+ });
372
+ return;
373
+ }
374
+ }
375
+ }
376
+ buildItem(event, distinctId, data) {
377
+ const item = {
378
+ website: this.cfg.websiteId,
379
+ name: event,
380
+ id: distinctId,
381
+ hy_event_id: crypto.randomUUID()
382
+ };
383
+ if (data) {
384
+ if (data.revenue !== undefined) {
385
+ item.revenue = String(data.revenue);
386
+ if (data.revenue > REVENUE_WARNING_THRESHOLD) {
387
+ this.log({
388
+ action: "track",
389
+ outcome: "warning",
390
+ message: `Revenue value ${data.revenue} looks unusually high — X-Ray expects dollars (e.g., 49.99), not cents. Divide by 100 if your payment provider returns cents.`,
391
+ event
392
+ });
393
+ }
394
+ }
395
+ if (data.currency !== undefined && !CURRENCY_PATTERN.test(data.currency)) {
396
+ this.log({
397
+ action: "track",
398
+ outcome: "warning",
399
+ message: `Currency "${data.currency}" does not match ISO 4217 format (expected 3 uppercase letters, e.g., "USD").`,
400
+ event
401
+ });
402
+ }
403
+ for (const key of DATA_KEYS) {
404
+ if (data[key] !== undefined)
405
+ item[key] = data[key];
406
+ }
407
+ if (data.metadata) {
408
+ const { data: sanitized, warnings } = this.sanitizeProperties(data.metadata);
409
+ if (sanitized)
410
+ item.data = sanitized;
411
+ for (const w of warnings) {
412
+ this.log({ action: "track", outcome: "drop", message: w, event });
413
+ }
414
+ }
415
+ }
416
+ for (const key of ATTRIBUTION_KEYS) {
417
+ const value = this.cfg.context[key];
418
+ if (value !== undefined)
419
+ item[key] = value;
420
+ }
421
+ return item;
422
+ }
423
+ sanitizeProperties(properties) {
424
+ const warnings = [];
425
+ const result = {};
426
+ let count = 0;
427
+ for (const [rawKey, rawValue] of Object.entries(properties)) {
428
+ if (count >= PROPERTY_LIMITS.maxProperties) {
429
+ warnings.push(`Exceeded ${PROPERTY_LIMITS.maxProperties} properties, remaining dropped`);
430
+ break;
431
+ }
432
+ const needsTruncation = rawKey.length > PROPERTY_LIMITS.maxKeyLength;
433
+ const key = needsTruncation ? rawKey.slice(0, PROPERTY_LIMITS.maxKeyLength) : rawKey;
434
+ if (needsTruncation) {
435
+ warnings.push(`Property key "${key}…" truncated to ${PROPERTY_LIMITS.maxKeyLength} chars`);
436
+ }
437
+ const value = rawValue ?? null;
438
+ if (value !== null && !FLAT_TYPES.has(typeof value)) {
439
+ warnings.push(`Property "${key}" has non-flat value (${typeof value}), dropped`);
440
+ continue;
441
+ }
442
+ if (typeof value === "string" && value.length > PROPERTY_LIMITS.maxStringValueLength) {
443
+ result[key] = value.slice(0, PROPERTY_LIMITS.maxStringValueLength);
444
+ warnings.push(`Property "${key}" value truncated to ${PROPERTY_LIMITS.maxStringValueLength} chars`);
445
+ } else
446
+ result[key] = value;
447
+ count++;
448
+ }
449
+ return {
450
+ data: count > 0 ? result : undefined,
451
+ warnings
452
+ };
453
+ }
454
+ resolveWaitUntil() {
455
+ return this.cfg.waitUntil ?? discoverWaitUntil();
456
+ }
457
+ log(entry) {
458
+ if (this.logFn)
459
+ this.logFn(entry);
460
+ }
461
+ }
462
+ var GLOBAL_KEY = Symbol.for("hellyeah.xray.instance");
463
+ var createXRay = (websiteId, options) => {
464
+ const g = globalThis;
465
+ const existing = g[GLOBAL_KEY];
466
+ if (existing)
467
+ return existing;
468
+ const instance = new XRay(websiteId, options);
469
+ g[GLOBAL_KEY] = instance;
470
+ return instance;
471
+ };
472
+ export {
473
+ cv,
474
+ createXRay,
475
+ XRay
476
+ };
@@ -0,0 +1,120 @@
1
+ var import_node_module = require("node:module");
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ function __accessProp(key) {
7
+ return this[key];
8
+ }
9
+ var __toCommonJS = (from) => {
10
+ var entry = (__moduleCache ??= new WeakMap).get(from), desc;
11
+ if (entry)
12
+ return entry;
13
+ entry = __defProp({}, "__esModule", { value: true });
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (var key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(entry, key))
17
+ __defProp(entry, key, {
18
+ get: __accessProp.bind(from, key),
19
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
20
+ });
21
+ }
22
+ __moduleCache.set(from, entry);
23
+ return entry;
24
+ };
25
+ var __moduleCache;
26
+ var __returnValue = (v) => v;
27
+ function __exportSetter(name, newValue) {
28
+ this[name] = __returnValue.bind(null, newValue);
29
+ }
30
+ var __export = (target, all) => {
31
+ for (var name in all)
32
+ __defProp(target, name, {
33
+ get: all[name],
34
+ enumerable: true,
35
+ configurable: true,
36
+ set: __exportSetter.bind(all, name)
37
+ });
38
+ };
39
+
40
+ // src/svelte/index.ts
41
+ var exports_svelte = {};
42
+ __export(exports_svelte, {
43
+ track: () => track,
44
+ pageview: () => pageview,
45
+ injectAnalytics: () => injectAnalytics,
46
+ identify: () => identify
47
+ });
48
+ module.exports = __toCommonJS(exports_svelte);
49
+
50
+ // src/client/queue.ts
51
+ var initQueue = () => {
52
+ if (typeof window !== "undefined") {
53
+ window._hy = window._hy || [];
54
+ }
55
+ };
56
+
57
+ // src/client/utils.ts
58
+ var DEFAULT_HOST = "https://xray-staging.hellyeahai.com";
59
+ var isBrowser = () => typeof window !== "undefined" && typeof document !== "undefined";
60
+ var isDevelopment = () => typeof process !== "undefined" && process.env?.NODE_ENV === "development";
61
+ var getDefaultHost = () => DEFAULT_HOST;
62
+
63
+ // src/client/generic.ts
64
+ var inject = (props) => {
65
+ if (!isBrowser())
66
+ return;
67
+ const { websiteId, domains, autoTrack = true, src } = props;
68
+ const hostUrl = props.hostUrl || getDefaultHost();
69
+ const scriptSrc = src || `${hostUrl}/script.js`;
70
+ if (document.head.querySelector(`script[src*="${scriptSrc}"]`))
71
+ return;
72
+ initQueue();
73
+ const dataset = {
74
+ websiteId,
75
+ hostUrl
76
+ };
77
+ if (domains)
78
+ dataset.domains = domains;
79
+ if (!autoTrack)
80
+ dataset.autoTrack = "false";
81
+ const script = document.createElement("script");
82
+ script.src = scriptSrc;
83
+ script.defer = true;
84
+ for (const [key, value] of Object.entries(dataset)) {
85
+ script.dataset[key] = value;
86
+ }
87
+ script.onerror = () => {
88
+ const msg = isDevelopment() ? "Please check if any ad blockers are enabled and try again." : "Check that the hostUrl is correct and the script is accessible.";
89
+ console.log(`[x-ray] Failed to load script from ${scriptSrc}. ${msg}`);
90
+ };
91
+ document.head.appendChild(script);
92
+ };
93
+ var track = (name, data) => {
94
+ if (!isBrowser())
95
+ return;
96
+ if (window.hy) {
97
+ window.hy.track(name, data);
98
+ } else {
99
+ initQueue();
100
+ window._hy = window._hy || [];
101
+ window._hy.push(["track", name, data]);
102
+ }
103
+ };
104
+ var identify = (id, data) => {
105
+ if (!isBrowser())
106
+ return;
107
+ if (window.hy) {
108
+ window.hy.identify(id, data);
109
+ } else {
110
+ initQueue();
111
+ window._hy = window._hy || [];
112
+ window._hy.push(["identify", id, data]);
113
+ }
114
+ };
115
+ var pageview = () => {
116
+ track();
117
+ };
118
+
119
+ // src/svelte/index.ts
120
+ var injectAnalytics = (props) => inject(props);
@@ -0,0 +1,31 @@
1
+ /** Props accepted by the `<Analytics />` component and `inject()`. */
2
+ type AnalyticsProps = {
3
+ /** Your x-ray website ID. */
4
+ websiteId: string;
5
+ /** Base URL of your x-ray server. @defaultValue `"https://xray-staging.hellyeahai.com"` */
6
+ hostUrl?: string;
7
+ /** Restrict tracking to this domain only. */
8
+ domains?: string;
9
+ /** Auto-track events on `data-hy-event` elements. @defaultValue true */
10
+ autoTrack?: boolean;
11
+ /** Custom `src` for the tracker script (overrides the default `/script.js`). */
12
+ src?: string;
13
+ };
14
+ /** Arbitrary event data passed to `track()`. */
15
+ type EventData = Record<string, string | number | boolean | null>;
16
+ /**
17
+ * Track a custom event. If the tracker script hasn't loaded yet, the call is
18
+ * buffered in `window._hy` and replayed once it initialises.
19
+ */
20
+ declare const track: (name?: string, data?: EventData) => void;
21
+ /**
22
+ * Identify the current user. Buffered if the tracker script hasn't loaded yet.
23
+ */
24
+ declare const identify: (id: string, data?: EventData) => void;
25
+ /**
26
+ * Record a pageview. Equivalent to calling `track()` with no arguments — the
27
+ * remote tracker interprets this as a pageview event.
28
+ */
29
+ declare const pageview: () => void;
30
+ declare const injectAnalytics: (props: AnalyticsProps) => void;
31
+ export { track, pageview, injectAnalytics, identify, AnalyticsProps };
@@ -0,0 +1,31 @@
1
+ /** Props accepted by the `<Analytics />` component and `inject()`. */
2
+ type AnalyticsProps = {
3
+ /** Your x-ray website ID. */
4
+ websiteId: string;
5
+ /** Base URL of your x-ray server. @defaultValue `"https://xray-staging.hellyeahai.com"` */
6
+ hostUrl?: string;
7
+ /** Restrict tracking to this domain only. */
8
+ domains?: string;
9
+ /** Auto-track events on `data-hy-event` elements. @defaultValue true */
10
+ autoTrack?: boolean;
11
+ /** Custom `src` for the tracker script (overrides the default `/script.js`). */
12
+ src?: string;
13
+ };
14
+ /** Arbitrary event data passed to `track()`. */
15
+ type EventData = Record<string, string | number | boolean | null>;
16
+ /**
17
+ * Track a custom event. If the tracker script hasn't loaded yet, the call is
18
+ * buffered in `window._hy` and replayed once it initialises.
19
+ */
20
+ declare const track: (name?: string, data?: EventData) => void;
21
+ /**
22
+ * Identify the current user. Buffered if the tracker script hasn't loaded yet.
23
+ */
24
+ declare const identify: (id: string, data?: EventData) => void;
25
+ /**
26
+ * Record a pageview. Equivalent to calling `track()` with no arguments — the
27
+ * remote tracker interprets this as a pageview event.
28
+ */
29
+ declare const pageview: () => void;
30
+ declare const injectAnalytics: (props: AnalyticsProps) => void;
31
+ export { track, pageview, injectAnalytics, identify, AnalyticsProps };