1+ ( function ( ) {
2+ const connectionString = window . APPLICATIONINSIGHTS_CONNECTION_STRING ;
3+
4+ if ( ! connectionString ) {
5+ return ;
6+ }
7+
8+ const script = document . createElement ( 'script' ) ;
9+ script . src = 'https://js.monitor.azure.com/scripts/b/ai.2.min.js' ;
10+ script . async = true ;
11+
12+ script . onload = function ( ) {
13+ const appInsights = new Microsoft . ApplicationInsights . ApplicationInsights ( {
14+ config : {
15+ connectionString : connectionString ,
16+ enableAutoRouteTracking : false ,
17+ disableExceptionTracking : true ,
18+ disableTelemetry : false ,
19+ samplingPercentage : 100
20+ }
21+ } ) ;
22+
23+ appInsights . loadAppInsights ( ) ;
24+
25+ // Generate anonymous user ID for session tracking
26+ const userId = sessionStorage . getItem ( 'ai_user' ) ||
27+ ( function ( ) {
28+ // Prefer cryptographically secure random values
29+ let randStr = '' ;
30+ if ( window . crypto && window . crypto . getRandomValues ) {
31+ // Generate 16 random bytes, then encode as hex
32+ const buf = new Uint8Array ( 16 ) ;
33+ window . crypto . getRandomValues ( buf ) ;
34+ randStr = Array . from ( buf , b => b . toString ( 16 ) . padStart ( 2 , '0' ) ) . join ( '' ) ;
35+ } else {
36+ // Fallback if crypto not supported (rare): use Math.random, but warn
37+ randStr = Math . random ( ) . toString ( 36 ) . substring ( 2 , 15 ) ;
38+ }
39+ return 'user_' + randStr ;
40+ } ) ( ) ;
41+ sessionStorage . setItem ( 'ai_user' , userId ) ;
42+ appInsights . setAuthenticatedUserContext ( userId ) ;
43+
44+ // Collect comprehensive user statistics
45+ const userStats = {
46+ referrer : document . referrer || 'direct' ,
47+ userAgent : navigator . userAgent ,
48+ language : navigator . language ,
49+ languages : navigator . languages ? navigator . languages . join ( ',' ) : '' ,
50+ screenResolution : `${ screen . width } x${ screen . height } ` ,
51+ colorDepth : screen . colorDepth ,
52+ timezone : Intl . DateTimeFormat ( ) . resolvedOptions ( ) . timeZone ,
53+ platform : navigator . platform ,
54+ cookieEnabled : navigator . cookieEnabled ,
55+ onLine : navigator . onLine ,
56+ deviceMemory : navigator . deviceMemory || 'unknown' ,
57+ connection : navigator . connection ? {
58+ effectiveType : navigator . connection . effectiveType ,
59+ downlink : navigator . connection . downlink ,
60+ rtt : navigator . connection . rtt
61+ } : 'unknown'
62+ } ;
63+
64+ // Track page view with enhanced user statistics
65+ appInsights . trackPageView ( {
66+ name : 'Tsunami Map' ,
67+ properties : userStats
68+ } ) ;
69+
70+ // Track user location (with permission)
71+ if ( navigator . geolocation && 'geolocation' in navigator ) {
72+ navigator . geolocation . getCurrentPosition (
73+ function ( position ) {
74+ // Track approximate location (country/region level for privacy)
75+ appInsights . trackEvent ( 'UserLocation' , {
76+ latitude : Math . round ( position . coords . latitude * 10 ) / 10 , // Rounded for privacy
77+ longitude : Math . round ( position . coords . longitude * 10 ) / 10 , // Rounded for privacy
78+ accuracy : position . coords . accuracy > 1000 ? 'low' : 'high'
79+ } ) ;
80+ } ,
81+ function ( error ) {
82+ // Track location access denied/failed
83+ appInsights . trackEvent ( 'LocationAccessDenied' , {
84+ error : error . message || 'unknown'
85+ } ) ;
86+ } ,
87+ { enableHighAccuracy : false , timeout : 5000 , maximumAge : 300000 }
88+ ) ;
89+ }
90+
91+ // Track map interactions
92+ window . trackMapInteraction = function ( action , properties ) {
93+ appInsights . trackEvent ( 'MapInteraction' , {
94+ action : action ,
95+ ...properties ,
96+ timestamp : new Date ( ) . toISOString ( )
97+ } ) ;
98+ } ;
99+
100+ // Track session duration
101+ let sessionStart = Date . now ( ) ;
102+ window . addEventListener ( 'beforeunload' , function ( ) {
103+ const sessionDuration = Math . round ( ( Date . now ( ) - sessionStart ) / 1000 ) ;
104+ appInsights . trackEvent ( 'SessionEnd' , {
105+ durationSeconds : sessionDuration ,
106+ userId : userId
107+ } ) ;
108+ } ) ;
109+ } ;
110+
111+ document . head . appendChild ( script ) ;
112+ } ) ( ) ;
0 commit comments