UNPKG

4.01 kBPlain TextView Raw
1import type {JsonObject, Wnd} from './types';
2import {doNotTrack, buildWarn, isBot} from './utils';
3import {version} from '../package.json';
4
5export {Wnd};
6const run = () => {
7 if (!window) return;
8 const isDnt = doNotTrack();
9
10 const {
11 // @ts-ignore
12 screen: {width, height},
13 // @ts-ignore
14 navigator: {language, userAgent},
15 location: {hostname, pathname, search, origin},
16 document,
17 history,
18 } = window;
19
20 const script = document.querySelector('script[data-site]');
21 if (!script) return console.error('script.js not found');
22
23 // @ts-ignore
24 const url = new URL(document.currentScript.src).origin;
25
26 const attr = (key: string) =>
27 script && (script.getAttribute(key) || script.getAttribute(`data-${key}`));
28
29 const shortcode = attr('site'); // shortcode
30 const dnt0ff = attr('dnt-off'); // shoud we send dnt=0?
31 const spa = attr('spa'); // is it spa
32 const warn = buildWarn();
33 const parsedHosthName = attr('hostname') || hostname;
34 // @ts-ignore
35 const canonical = attr('canonical'); // should we monitor canonical urls
36
37 if (!shortcode) return warn('site not found');
38 if (isBot(userAgent)) return warn('bot detected');
39 if (dnt0ff && isDnt) return warn('dnt-off and dnt=1');
40
41 if (
42 'visibilityState' in document &&
43 // @ts-ignore
44 'prerender' === document.visibilityState
45 ) {
46 return warn('Prerendering');
47 }
48
49 const historyAttached = () => {
50 const pushState = history.pushState;
51 if (void 0 !== history) {
52 history.pushState = function () {
53 var output = pushState.apply(history, arguments as any);
54 return (
55 window.dispatchEvent(new Event('pushstate')),
56 window.dispatchEvent(new Event('prxm')),
57 output
58 );
59 };
60 window.addEventListener('popstate', function () {
61 window.dispatchEvent(new Event('prxm'));
62 });
63 window.addEventListener('prxm', monitor);
64 }
65 };
66
67 const hashAttached = () => {
68 window.addEventListener('hashchange', monitor);
69 };
70
71 const init = () => {
72 warn('init');
73
74 if (spa) {
75 switch (spa) {
76 case 'history':
77 historyAttached();
78 break;
79 case 'hash':
80 hashAttached();
81 break;
82 default:
83 void 0 !== history ? historyAttached() : hashAttached();
84 }
85 } else {
86 window.addEventListener('load', monitor);
87 }
88 };
89
90 const pxl = (p: string, e: JsonObject) => {
91 const element = document.createElement('img') as HTMLImageElement;
92 element.setAttribute('aria-hidden', 'true');
93 element.setAttribute('alt', '');
94 element.src = url + e.toString();
95 element.style.position = 'absolute';
96 // @ts-ignore
97 element.src = url + p + '/pixel?' + new URLSearchParams(e).toString();
98 element.addEventListener('load', function () {
99 element.parentNode && element.parentNode.removeChild(element);
100 });
101 element.addEventListener('error', function () {
102 element.parentNode && element.parentNode.removeChild(element);
103 });
104 document.body.appendChild(element);
105 };
106 // @ts-ignore
107 const event = (e: JsonObject) => {};
108
109 const send = (p: string, data: JsonObject) => {
110 const xhr = new XMLHttpRequest();
111 xhr.open('POST', url + p, true);
112 xhr.setRequestHeader('Content-Type', 'text/plain');
113 xhr.addEventListener('error', function () {
114 pxl(p, data);
115 });
116 xhr.send(JSON.stringify(data));
117 };
118
119 const monitor = () => {
120 const data = {
121 p: origin + pathname + search,
122 v: version,
123 s: shortcode,
124 h: parsedHosthName,
125 r: document.referrer,
126 cid: Date.now().toString(32),
127 // @ts-ignore
128 l: navigator.userLanguage || navigator.language || '',
129 // performance metrics
130 };
131 send('/hit/torch', data);
132 };
133
134 // @ts-ignore
135 const monitorEvent = () => {};
136
137 if (!(window as Wnd).proxima) {
138 const proxima = {
139 monitor: monitor,
140 event: monitor,
141 };
142 (window as Wnd).proxima = proxima;
143 init();
144 }
145};
146run();