PageSourceSearch

https://omarismailo.com/tracker.js

js omarismailo.com collected 2026-10-02 00:53:54 UTC 11,142 bytes, 196 lines download raw bytes

1/**
2 * OI Analytics Tracker v2.0
3 * Comprehensive visitor tracking for omarismailo.com
4 * Add to your site: <script src="tracker.js" defer></script>
5 */
6(function(){
7    'use strict';
8    const OIT = {
9        sid: function(){
10            let s = sessionStorage.getItem('oi_sid');
11            if(!s){ s = 's_'+Date.now()+'_'+Math.random().toString(36).substr(2,9); sessionStorage.setItem('oi_sid',s); }
12            return s;
13        },
14        vid: function(){
15            let v = localStorage.getItem('oi_vid');
16            if(!v){ v = 'v_'+Date.now()+'_'+Math.random().toString(36).substr(2,9); localStorage.setItem('oi_vid',v); }
17            return v;
18        },
19        isNew: function(){ return !localStorage.getItem('oi_returning'); },
20        parseUA: function(){
21            const u = navigator.userAgent;
22            let b='Unknown', os='Unknown', d='Desktop', bv='';
23            if(/CriOS/i.test(u)) b='Chrome iOS';
24            else if(/FxiOS/i.test(u)) b='Firefox iOS';
25            else if(/EdgA/i.test(u)) b='Edge Android';
26            else if(/Edg\//i.test(u)){ b='Edge'; bv=(u.match(/Edg\/([\d.]+)/)||[])[1]||''; }
27            else if(/OPR|Opera/i.test(u)) b='Opera';
28            else if(/SamsungBrowser/i.test(u)) b='Samsung';
29            else if(/UCBrowser/i.test(u)) b='UC Browser';
30            else if(/Chrome/i.test(u)){ b='Chrome'; bv=(u.match(/Chrome\/([\d.]+)/)||[])[1]||''; }
31            else if(/Safari/i.test(u)&&!/Chrome/i.test(u)){ b='Safari'; bv=(u.match(/Version\/([\d.]+)/)||[])[1]||''; }
32            else if(/Firefox/i.test(u)){ b='Firefox'; bv=(u.match(/Firefox\/([\d.]+)/)||[])[1]||''; }
33            else if(/MSIE|Trident/i.test(u)) b='IE';
34            if(/Windows NT 10/i.test(u)) os='Windows 10/11';
35            else if(/Windows/i.test(u)) os='Windows';
36            else if(/Mac OS X/i.test(u)&&!/iPhone|iPad/i.test(u)){ os='macOS'; }
37            else if(/Android ([\d.]+)/i.test(u)){ os='Android '+(u.match(/Android ([\d.]+)/)||[])[1]; }
38            else if(/iPhone OS ([\d_]+)/i.test(u)){ os='iOS '+(u.match(/iPhone OS ([\d_]+)/)||[])[1].replace(/_/g,'.'); }
39            else if(/iPad/i.test(u)) os='iPadOS';
40            else if(/Linux/i.test(u)) os='Linux';
41            else if(/CrOS/i.test(u)) os='ChromeOS';
42            if(/Mobile|Android.*Mobile|iPhone/i.test(u)) d='Mobile';
43            else if(/iPad|Android(?!.*Mobile)|Tablet/i.test(u)) d='Tablet';
44            return { browser:b, browserVersion:bv, os:os, device:d };
45        },
46        getSource: function(){
47            const r = document.referrer;
48            const u = new URL(window.location.href);
49            const utm_s = u.searchParams.get('utm_source');
50            const utm_m = u.searchParams.get('utm_medium');
51            const utm_c = u.searchParams.get('utm_campaign');
52            const utm_t = u.searchParams.get('utm_term');
53            const utm_ct = u.searchParams.get('utm_content');
54            let source='Direct', medium='none', campaign='', keyword='';
55            if(utm_s){ source=utm_s; medium=utm_m||''; campaign=utm_c||''; keyword=utm_t||''; }
56            else if(r){
57                try{
58                    const rh = new URL(r).hostname.toLowerCase();
59                    if(/google\./i.test(rh)){source='Google';medium='organic';}
60                    else if(/bing\./i.test(rh)){source='Bing';medium='organic';}
61                    else if(/yahoo\./i.test(rh)){source='Yahoo';medium='organic';}
62                    else if(/duckduckgo/i.test(rh)){source='DuckDuckGo';medium='organic';}
63                    else if(/yandex/i.test(rh)){source='Yandex';medium='organic';}
64                    else if(/baidu/i.test(rh)){source='Baidu';medium='organic';}
65                    else if(/facebook\.com|fb\.com/i.test(rh)){source='Facebook';medium='social';}
66                    else if(/instagram/i.test(rh)){source='Instagram';medium='social';}
67                    else if(/twitter\.com|x\.com|t\.co/i.test(rh)){source='Twitter/X';medium='social';}
68                    else if(/linkedin/i.test(rh)){source='LinkedIn';medium='social';}
69                    else if(/whatsapp|wa\.me/i.test(rh)){source='WhatsApp';medium='social';}
70                    else if(/tiktok/i.test(rh)){source='TikTok';medium='social';}
71                    else if(/youtube/i.test(rh)){source='YouTube';medium='social';}
72                    else if(/snapchat/i.test(rh)){source='Snapchat';medium='social';}
73                    else if(/reddit/i.test(rh)){source='Reddit';medium='social';}
74                    else if(/pinterest/i.test(rh)){source='Pinterest';medium='social';}
75                    else if(/telegram/i.test(rh)){source='Telegram';medium='social';}
76                    else{source=rh;medium='referral';}
77                }catch(e){source='Unknown';medium='referral';}
78            }
79            if(u.searchParams.get('fbclid')){source='Facebook';medium='paid_social';}
80            if(u.searchParams.get('gclid')){source='Google Ads';medium='cpc';}
81            if(u.searchParams.get('msclkid')){source='Bing Ads';medium='cpc';}
82            return {source,medium,campaign,keyword,utm_content:utm_ct||'',referrer:r||'Direct'};
83        },
84        getPerf: function(){
85            try{
86                const p=performance.getEntriesByType('navigation')[0];
87                return {
88                    dns:Math.round(p.domainLookupEnd-p.domainLookupStart),
89                    tcp:Math.round(p.connectEnd-p.connectStart),
90                    ttfb:Math.round(p.responseStart-p.requestStart),
91                    domReady:Math.round(p.domContentLoadedEventEnd-p.startTime),
92                    fullLoad:Math.round(p.loadEventEnd-p.startTime),
93                    type:p.type
94                };
95            }catch(e){return {dns:0,tcp:0,ttfb:0,domReady:0,fullLoad:0,type:'navigate'};}
96        },
97        track: function(){
98            const ua = this.parseUA();
99            const src = this.getSource();
100            const perf = this.getPerf();
101            const visitor = {
102                id: this.sid(), vid: this.vid(), isNew: this.isNew(),
103                timestamp: new Date().toISOString(), ts: Date.now(),
104                page: window.location.pathname + window.location.search,
105                title: document.title, hash: window.location.hash,
106                browser: ua.browser, browserVersion: ua.browserVersion,
107                os: ua.os, device: ua.device,
108                screen: screen.width+'x'+screen.height,
109                viewport: window.innerWidth+'x'+window.innerHeight,
110                pixelRatio: window.devicePixelRatio||1,
111                colorDepth: screen.colorDepth||24,
112                language: navigator.language||'unknown',
113                languages: (navigator.languages||[]).join(','),
114                timezone: Intl.DateTimeFormat().resolvedOptions().timeZone||'unknown',
115                cookiesEnabled: navigator.cookieEnabled,
116                doNotTrack: navigator.doNotTrack==='1',
117                online: navigator.onLine,
118                connection: (navigator.connection||{}).effectiveType||'unknown',
119                downlink: (navigator.connection||{}).downlink||0,
120                cores: navigator.hardwareConcurrency||0,
121                memory: navigator.deviceMemory||0,
122                touchPoints: navigator.maxTouchPoints||0,
123                source: src.source, medium: src.medium, campaign: src.campaign,
124                keyword: src.keyword, utm_content: src.utm_content, referrer: src.referrer,
125                perf: perf, scrollMax: 0, clicks: 0, duration: 0,
126                country:'', countryCode:'', city:'', region:'', isp:'', ip:'',
127                lat:0, lon:0, org:'', zip:'', exitPage:''
128            };
129            // Geo lookup
130            fetch('https://ip-api.com/json/?fields=66846719')
131            .then(r=>r.json()).then(d=>{
132                if(d.status==='success'){
133                    visitor.country=d.country; visitor.countryCode=d.countryCode;
134                    visitor.city=d.city; visitor.region=d.regionName;
135                    visitor.isp=d.isp; visitor.ip=d.query;
136                    visitor.lat=d.lat; visitor.lon=d.lon;
137                    visitor.org=d.org; visitor.zip=d.zip;
138                }
139                OIT.save(visitor);
140            }).catch(()=>OIT.save(visitor));
141            // Scroll depth
142            let maxS=0;
143            window.addEventListener('scroll',function(){
144                const h=document.documentElement.scrollHeight-window.innerHeight;
145                const p=h>0?Math.round((window.scrollY/h)*100):0;
146                if(p>maxS){maxS=p;visitor.scrollMax=p;}
147            },{passive:true});
148            // Clicks
149            document.addEventListener('click',function(e){
150                visitor.clicks++;
151                const t=e.target.closest('a,button');
152                if(t){
153                    const ce={ts:Date.now(),tag:t.tagName,text:(t.textContent||'').trim().substring(0,50),href:t.href||'',section:t.closest('section')?.id||''};
154                    let clicks=[];try{clicks=JSON.parse(localStorage.getItem('oi_clicks')||'[]')}catch(x){}
155                    clicks.push(ce);if(clicks.length>1000)clicks=clicks.slice(-1000);
156                    try{localStorage.setItem('oi_clicks',JSON.stringify(clicks))}catch(x){}
157                }
158            });
159            // Page views (multi-page tracking)
160            let pvs=[];try{pvs=JSON.parse(localStorage.getItem('oi_pageviews')||'[]')}catch(x){}
161            pvs.push({page:visitor.page,ts:visitor.ts,title:visitor.title});
162            if(pvs.length>2000) pvs=pvs.slice(-2000);
163            try{localStorage.setItem('oi_pageviews',JSON.stringify(pvs))}catch(x){}
164            // Duration + save on unload
165            const saveOnExit = () => {
166                visitor.duration=Math.round((Date.now()-visitor.ts)/1000);
167                visitor.exitPage=window.location.pathname;
168                OIT.save(visitor);
169            };
170            window.addEventListener('beforeunload', saveOnExit);
171            document.addEventListener('visibilitychange', function(){
172                if(document.hidden) saveOnExit();
173            });
174            // Auto-save every 10 seconds
175            setInterval(()=>{
176                visitor.duration=Math.round((Date.now()-visitor.ts)/1000);
177                OIT.save(visitor);
178            },10000);
179            // Mark returning
180            setTimeout(()=>localStorage.setItem('oi_returning','1'),3000);
181        },
182        save: function(v){
183            let visits=[];
184            try{visits=JSON.parse(localStorage.getItem('oi_analytics')||'[]')}catch(e){visits=[];}
185            const idx = visits.findIndex(x=>x.id===v.id);
186            if(idx>-1) visits[idx]=v; else visits.push(v);
187            if(visits.length>5000) visits=visits.slice(-5000);
188            try{localStorage.setItem('oi_analytics',JSON.stringify(visits))}catch(e){
189                visits=visits.slice(-2500);
190                try{localStorage.setItem('oi_analytics',JSON.stringify(visits))}catch(x){}
191            }
192        }
193    };
194    if(document.readyState==='loading') document.addEventListener('DOMContentLoaded',()=>OIT.track());
195    else OIT.track();
196})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.