1/* 2 * Looke - Session Replay 3 * 4 * Loader unico para Microsoft Clarity e PostHog. 5 * A pagina recebe window.__lookeReplay pelo middleware. 6 */ 7(function (w, d) { 8 'use strict'; 9 10 if (w.SessionReplay) { return; } 11 12 var cfg = w.__lookeReplay || null; 13 if (!cfg || !cfg.enabled) { return; } 14 15 var ROLL_KEY = '__lk_sr_roll_v1'; 16 var CONSENT_KEY = '__lk_sr_consent_v1'; 17 18 var ready = { clarity: false, posthog: false }; 19 var loaded = { clarity: false, posthog: false }; 20 var pending = []; 21 var active = []; 22 var linked = false; 23 var started = false; 24 var posthogRecordingLimitTimer = null; 25 26 function log() { 27 if (!cfg.debug || !w.console || !w.console.log) { return; } 28 w.console.log.apply(w.console, ['[SessionReplay]'].concat([].slice.call(arguments))); 29 } 30 31 function storageGet(storage, key) { 32 try { return storage.getItem(key); } catch (e) { return null; } 33 } 34 35 function storageSet(storage, key, value) { 36 try { storage.setItem(key, value); } catch (e) { } 37 } 38 39 function hasConsent() { 40 if (!cfg.requireConsent) { return true; } 41 42 return storageGet(w.localStorage, CONSENT_KEY) === 'true'; 43 } 44 45 function dice() { 46 var stored = storageGet(w.sessionStorage, ROLL_KEY); 47 48 if (stored === null) { 49 stored = String(Math.floor(Math.random() * 100)); 50 storageSet(w.sessionStorage, ROLL_KEY, stored); 51 } 52 53 var parsed = parseInt(stored, 10); 54 55 if (isNaN(parsed) || parsed < 0 || parsed > 99) { 56 parsed = Math.floor(Math.random() * 100); 57 storageSet(w.sessionStorage, ROLL_KEY, String(parsed)); 58 } 59 60 return parsed; 61 } 62 63 var roll = dice(); 64 65 function sampled(rate) { 66 return typeof rate === 'number' && rate > 0 && roll < rate; 67 } 68 69 function selectorList(list) { 70 return list && list.length ? list.join(',') : null; 71 } 72 73 function addClass(node, className) { 74 if (!node || !className) { return; } 75 76 if (node.classList && node.classList.add) { 77 node.classList.add(className); 78 return; 79 } 80 81 var current = node.className || ''; 82 if (typeof current === 'string' && (' ' + current + ' ').indexOf(' ' + className + ' ') < 0) { 83 node.className = current ? current + ' ' + className : className; 84 } 85 } 86 87 function safeQuerySelectorAll(selector) { 88 if (!selector) { return []; } 89 90 try { 91 return d.querySelectorAll(selector); 92 } catch (e) { 93 log('seletor invalido', selector, e); 94 return []; 95 } 96 } 97 98 function querySelectors(list) { 99 var result = []; 100 101 if (!list || !list.length) { return result; } 102 103 for (var i = 0; i < list.length; i++) { 104 var nodes = safeQuerySelectorAll(list[i]); 105 106 for (var j = 0; j < nodes.length; j++) { 107 result.push(nodes[j]); 108 } 109 } 110 111 return result; 112 } 113 114 function applyMaskAttributes() { 115 var maskNodes = querySelectors(cfg.maskSelectors); 116 for (var i = 0; i < maskNodes.length; i++) { 117 maskNodes[i].setAttribute('data-clarity-mask', 'True'); 118 addClass(maskNodes[i], 'ph-mask'); 119 } 120 121 var blockNodes = querySelectors(cfg.blockSelectors); 122 for (var j = 0; j < blockNodes.length; j++) { 123 blockNodes[j].setAttribute('data-clarity-mask', 'True'); 124 addClass(blockNodes[j], 'ph-no-capture'); 125 } 126 } 127 128 function watchDynamicDom() { 129 applyMaskAttributes(); 130 131 if (d.readyState === 'loading') { 132 d.addEventListener('DOMContentLoaded', applyMaskAttributes); 133 } 134 135 try { 136 if (w.jQuery) { 137 w.jQuery(d).ajaxComplete(applyMaskAttributes); 138 } 139 } catch (e) { } 140 141 try { 142 var observer = new MutationObserver(function () { 143 applyMaskAttributes(); 144 }); 145 146 observer.observe(d.documentElement || d.body, { 147 childList: true, 148 subtree: true 149 }); 150 } catch (e) { } 151 } 152 153 function normalizeKey(key) { 154 return String(key || '') 155 .replace(/([a-z0-9])([A-Z])/g, '$1_$2') 156 .toLowerCase() 157 .normalize('NFD') 158 .replace(/[\u0300-\u036f]/g, ''); 159 } 160 161 function isSensitiveKey(key) { 162 var normalized = normalizeKey(key); 163 164 return /(^|[_\-.:\\/\s])(password|senha|pass|passwd|pwd|secret|token|document|documento|cpf|cnpj|card|cartao|cvv|security|email|e_mail|phone|telefone|celular|mobile|address|endereco|cep)($|[_\-.:\\/\s])/.test(normalized) || 165 /credit[_\-.:\\/\s]*card|numero[_\-.:\\/\s]*cartao|cartao[_\-.:\\/\s]*credito|postal[_\-.:\\/\s]*code/.test(normalized); 166 } 167 168 function isPostHogInternalKey(key) { 169 if (!key) { return false; } 170 171 return key === 'token' || 172 key === 'api_key' || 173 key === 'distinct_id' || 174 key === '$distinct_id' || 175 key.charAt(0) === '$'; 176 } 177
178 function sanitizeValue(key, value, options) { 179 var urlLike = /url|href|uri|link|referrer/i; 180 var preservePostHogInternals = !!(options && options.preservePostHogInternals); 181 182 if (key === '$set' || key === '$set_once') { 183 return sanitizeProperties(value); 184 } 185 186 if (urlLike.test(key || '') && typeof value === 'string') { 187 return sanitizeUrl(value); 188 } 189 190 if (preservePostHogInternals && isPostHogInternalKey(key)) { 191 return value; 192 } 193 194 if (isSensitiveKey(key)) { 195 return '[masked]'; 196 } 197 198 if (Array.isArray(value)) { 199 return value.map(function (item) { 200 return sanitizeValue('', item, options); 201 }); 202 } 203 204 if (value && typeof value === 'object') { 205 return sanitizeProperties(value, options); 206 } 207 208 return value; 209 } 210 211 function sanitizeProperties(props, options) { 212 if (!props || typeof props !== 'object') { return props; } 213 214 var clean = {}; 215 216 for (var key in props) { 217 if (!Object.prototype.hasOwnProperty.call(props, key)) { continue; } 218 219 clean[key] = sanitizeValue(key, props[key], options); 220 } 221 222 return clean; 223 } 224 225 function sanitizeUrl(value) { 226 if (!value || typeof value !== 'string') { return value; } 227 228 try { 229 var url = new URL(value, w.location.origin); 230 url.search = ''; 231 url.hash = ''; 232 return url.toString(); 233 } catch (e) { 234 return value.split('?')[0].split('#')[0]; 235 } 236 } 237 238 function getPostHogMaxRecordingSeconds() { 239 var value = cfg.posthog ? cfg.posthog.maxRecordingSeconds : null; 240 241 if (value === null || value === undefined || value === '') { return 0; } 242 243 var seconds = parseInt(value, 10); 244 245 if (isNaN(seconds) || seconds <= 0) { return 0; } 246 247 return seconds; 248 } 249 250 function schedulePostHogRecordingLimit() { 251 var seconds = getPostHogMaxRecordingSeconds(); 252 253 if (!seconds || !w.posthog || !w.posthog.stopSessionRecording) { return; } 254 255 if (posthogRecordingLimitTimer) { 256 w.clearTimeout(posthogRecordingLimitTimer); 257 } 258 259 posthogRecordingLimitTimer = w.setTimeout(function () { 260 try { 261 if (w.posthog && w.posthog.stopSessionRecording) { 262 w.posthog.stopSessionRecording(); 263 log('posthog session replay pausado por limite de tempo', seconds); 264 } 265 } catch (e) { 266 log('posthog stopSessionRecording falhou', e); 267 } 268 }, seconds * 1000); 269 } 270 271 function roundSeconds(value) { 272 if (typeof value !== 'number' || !isFinite(value)) { return null; } 273 274 return Math.round(value * 100) / 100; 275 } 276 277 function getQueryParam(name) { 278 try { 279 return new URL(w.location.href).searchParams.get(name); 280 } catch (e) { 281 var match = w.location.search.match(new RegExp('[?&]' + name + '=([^&]+)')); 282 return match ? decodeURIComponent(match[1].replace(/\+/g, ' ')) : null; 283 } 284 } 285 286 function buildPlayerEventProps(video, extra) { 287 var currentSeconds = video ? roundSeconds(video.currentTime) : null; 288 var durationSeconds = video ? roundSeconds(video.duration) : null; 289 var percent = null; 290 291 if (currentSeconds !== null && durationSeconds && durationSeconds > 0) { 292 percent = Math.round((currentSeconds * 100 / durationSeconds) * 100) / 100; 293 } 294 295 var props = { 296 video_id: video && video.id ? video.id : null, 297 media_id: getQueryParam('m'), 298 current_seconds: currentSeconds, 299 duration_seconds: durationSeconds, 300 percent: percent, 301 current_url: sanitizeUrl(w.location.href) 302 }; 303 304 extra = extra || {}; 305 306 for (var key in extra) { 307 if (Object.prototype.hasOwnProperty.call(extra, key)) { 308 props[key] = extra[key]; 309 } 310 } 311 312 return props; 313 } 314 315 function trackPlayerEvent(name, video, extra) { 316 try { 317 SessionReplay.track(name, buildPlayerEventProps(video, extra)); 318 } catch (e) { 319 log('player event falhou', name, e); 320 } 321 } 322 323 function attachPlayerEventTracking(video) { 324 if (!video || video.__lookeSessionReplayPlayerEvents) { return; } 325 326 video.__lookeSessionReplayPlayerEvents = true; 327 328 var state = { 329 ready: false, 330 started: false, 331 ended: false, 332 errored: false, 333 buffering: false, 334 bufferingStartedAt: null, 335 milestones: { 336 25: false, 337 50: false, 338 75: false,
339 95: false 340 } 341 }; 342 343 function markReady() { 344 if (state.ready) { return; } 345 346 state.ready = true; 347 trackPlayerEvent('looke_player_ready', video); 348 } 349 350 function markStarted() { 351 if (!state.started) { 352 state.started = true; 353 trackPlayerEvent('looke_player_started', video); 354 } 355 356 if (state.buffering) { 357 var elapsedSeconds = state.bufferingStartedAt ? roundSeconds((Date.now() - state.bufferingStartedAt) / 1000) : null; 358 state.buffering = false; 359 state.bufferingStartedAt = null; 360 trackPlayerEvent('looke_player_buffering_end', video, { buffering_seconds: elapsedSeconds }); 361 } 362 } 363 364 function markBuffering() { 365 if (state.buffering || state.ended) { return; } 366 367 state.buffering = true; 368 state.bufferingStartedAt = Date.now(); 369 trackPlayerEvent('looke_player_buffering_start', video); 370 } 371 372 function markProgress() { 373 var currentSeconds = roundSeconds(video.currentTime); 374 var durationSeconds = roundSeconds(video.duration); 375 376 if (currentSeconds === null || !durationSeconds || durationSeconds <= 0) { return; } 377 378 var percent = currentSeconds * 100 / durationSeconds; 379 var marks = [25, 50, 75, 95]; 380 381 for (var i = 0; i < marks.length; i++) { 382 var mark = marks[i]; 383 384 if (!state.milestones[mark] && percent >= mark) { 385 state.milestones[mark] = true; 386 trackPlayerEvent('looke_player_progress', video, { milestone: mark }); 387 } 388 } 389 } 390 391 function markEnded() { 392 if (state.ended) { return; } 393 394 state.ended = true; 395 trackPlayerEvent('looke_player_ended', video); 396 } 397 398 function markError() { 399 // Video sem src (preview decorativa de pagina de detalhes) dispara 400 // error trivial; e um mesmo load com varios <source> dispara um error 401 // por source. Sem isto, o painel enche de looke_player_error repetido. 402 if (!video.currentSrc && !video.src) { return; } 403 if (state.errored) { return; } 404 405 state.errored = true; 406 407 var error = video.error || {}; 408 409 trackPlayerEvent('looke_player_error', video, { 410 error_code: error.code || null 411 }); 412 } 413 414 function resetErrorOnNewLoad() { 415 state.errored = false; 416 } 417 418 video.addEventListener('loadeddata', markReady); 419 video.addEventListener('loadedmetadata', markReady); 420 video.addEventListener('play', markStarted); 421 video.addEventListener('playing', markStarted); 422 video.addEventListener('waiting', markBuffering); 423 video.addEventListener('stalled', markBuffering); 424 video.addEventListener('timeupdate', markProgress); 425 video.addEventListener('seeked', function () { 426 trackPlayerEvent('looke_player_seeked', video); 427 }); 428 video.addEventListener('ended', markEnded); 429 video.addEventListener('error', markError); 430 video.addEventListener('loadstart', resetErrorOnNewLoad); 431 } 432 433 function attachPlayerEventTrackingToPage() { 434 var videos = d.getElementsByTagName('video'); 435 436 for (var i = 0; i < videos.length; i++) { 437 attachPlayerEventTracking(videos[i]); 438 } 439 } 440 441 function watchPlayerEvents() { 442 attachPlayerEventTrackingToPage(); 443 444 if (d.readyState === 'loading') { 445 d.addEventListener('DOMContentLoaded', attachPlayerEventTrackingToPage); 446 } 447 448 try { 449 var observer = new MutationObserver(function () { 450 attachPlayerEventTrackingToPage(); 451 }); 452 453 observer.observe(d.documentElement || d.body, { 454 childList: true, 455 subtree: true 456 }); 457 } catch (e) { } 458 } 459 460 var DRIVERS = {}; 461 462 DRIVERS.clarity = { 463 name: 'clarity', 464 465 enabled: function () { 466 return !!(cfg.clarity && cfg.clarity.projectId && sampled(cfg.clarity.sampleRate)); 467 }, 468 469 load: function () { 470 if (loaded.clarity) { return; }
471 loaded.clarity = true; 472 473 (function (c, l, a, r, i, t, y) { 474 c[a] = c[a] || function () { (c[a].q = c[a].q || []).push(arguments); }; 475 t = l.createElement(r); 476 t.async = 1; 477 t.src = 'https://www.clarity.ms/tag/' + encodeURIComponent(i); 478 y = l.getElementsByTagName(r)[0]; 479 y.parentNode.insertBefore(t, y); 480 })(w, d, 'clarity', 'script', cfg.clarity.projectId); 481 482 ready.clarity = true; 483 log('clarity carregado'); 484 }, 485 486 identify: function (user) { 487 if (!user || !user.distinctId || !w.clarity) { return; } 488 489 w.clarity('identify', String(user.distinctId)); 490 491 if (user.userId) { w.clarity('set', 'looke_user_id', String(user.userId)); } 492 if (user.profileId) { w.clarity('set', 'looke_profile_id', String(user.profileId)); } 493 if (user.planId) { w.clarity('set', 'looke_plan_id', String(user.planId)); } 494 if (user.rid) { w.clarity('set', 'looke_rid', String(user.rid)); } 495 }, 496 497 track: function (name, props) { 498 if (!w.clarity) { return; } 499 500 w.clarity('event', String(name)); 501 502 var clean = sanitizeProperties(props); 503 for (var key in clean) { 504 if (Object.prototype.hasOwnProperty.call(clean, key) && clean[key] !== null && clean[key] !== undefined) { 505 w.clarity('set', String(key), String(clean[key])); 506 } 507 } 508 }, 509 510 tag: function (key, value) { 511 if (w.clarity) { 512 w.clarity('set', String(key), String(value)); 513 } 514 }, 515 516 upgrade: function (reason) { 517 if (w.clarity) { 518 w.clarity('upgrade', String(reason || 'important')); 519 } 520 }, 521 522 sessionUrl: function () { 523 try { 524 var match = d.cookie.match(/(?:^|;\s*)_clsk=([^;]+)/); 525 if (!match) { return null; } 526 527 var id = decodeURIComponent(match[1]).split('|')[0]; 528 if (!id) { return null; } 529 530 return 'https://clarity.microsoft.com/projects/view/' + cfg.clarity.projectId + 531 '/impressions?SessionId=' + encodeURIComponent(id); 532 } catch (e) { 533 return null; 534 } 535 } 536 }; 537 538 DRIVERS.posthog = { 539 name: 'posthog', 540 541 enabled: function () { 542 return !!(cfg.posthog && cfg.posthog.apiKey && sampled(cfg.posthog.sampleRate)); 543 }, 544 545 load: function () { 546 if (loaded.posthog) { return; } 547 loaded.posthog = true; 548 549 try { 550 ensurePostHogBootstrap(); 551 w.posthog.init(cfg.posthog.apiKey, buildPostHogOptions()); 552 } catch (e) { 553 log('posthog init falhou', e); 554 } 555 }, 556 557 identify: function (user) { 558 if (!user || !user.distinctId || !w.posthog) { return; } 559 560 w.posthog.identify(String(user.distinctId), { 561 looke_user_id: user.userId || null, 562 looke_profile_id: user.profileId || null, 563 looke_plan_id: user.planId || null, 564 looke_rid: user.rid || null 565 }); 566 }, 567 568 track: function (name, props) { 569 if (w.posthog) { 570 w.posthog.capture(String(name), sanitizeProperties(props) || {}); 571 } 572 }, 573 574 tag: function (key, value) { 575 if (!w.posthog) { return; } 576 577 var payload = {}; 578 payload[key] = value; 579 w.posthog.register(sanitizeProperties(payload)); 580 }, 581 582 upgrade: function () { 583 }, 584 585 sessionUrl: function () { 586 try { 587 return w.posthog && w.posthog.get_session_replay_url ? w.posthog.get_session_replay_url() : null; 588 } catch (e) { 589 return null; 590 } 591 } 592 }; 593 594 function ensurePostHogBootstrap() { 595 if (w.posthog && w.posthog.__loaded) { return; } 596 if (w.posthog && w.posthog.__SV && typeof w.posthog.init === 'function') { return; } 597 598 var posthog = w.posthog || []; 599 var script = null; 600 601 function bind(target, method) { 602 var parts = method.split('.'); 603 if (parts.length === 2) { 604 target = target[parts[0]]; 605 method = parts[1]; 606 } 607 608 target[method] = function () { 609 target.push([method].concat(Array.prototype.slice.call(arguments, 0))); 610 }; 611 } 612 613 posthog._i = posthog._i || []; 614 615 posthog.init = function (apiKey, options, name) { 616 var instance = posthog; 617 618 if (!script) { 619 script = d.createElement('script'); 620 script.type = 'text/javascript'; 621 script.crossOrigin = 'anonymous'; 622 script.async = true; 623 // Versao pinada: a 1.418.5 (19/08/2026) parou de gerar session no 624 // replay; a 1.418.4 era a versao que funcionava de manha. Sem o pin, 625 // /static/array.js entrega sempre o ultimo release deles. 626 script.src = resolvePostHogAssetHost(options) + '/static/1.418.4/array.js'; 627 script.onerror = function () { 628 script = null; 629 log('posthog bloqueado ou indisponivel'); 630 }; 631 632 var firstScript = d.getElementsByTagName('script')[0]; 633 firstScript.parentNode.insertBefore(script, firstScript); 634 } 635 636 if (typeof name !== 'undefined') { 637 instance = posthog[name] = []; 638 } else { 639 name = 'posthog'; 640 } 641 642 instance.people = instance.people || []; 643 instance.toString = function (loaded) { 644 var label = 'posthog'; 645 if (name !== 'posthog') { label += '.' + name; } 646 if (!loaded) { label += ' (stub)'; } 647 return label; 648 }; 649 instance.people.toString = function () { 650 return instance.toString(1) + '.people (stub)'; 651 }; 652 653 var methods = 'capture identify setPersonProperties unsetPersonProperties group resetGroups setGroupPropertiesForFlags resetPersonPropertiesForFlags setGroupPropertiesForFlags reset resetGroups shutdown register register_once register_for_session unregister unregister_for_session getFeatureFlag getFeatureFlagPayload getFeatureFlagResult getAllFeatureFlags isFeatureEnabled reloadFeatureFlags updateFlags on onFeatureFlags onSessionId alias set_config startSessionRecording stopSessionRecording sessionRecordingStarted captureException captureLog get_property getSessionProperty get_distinct_id getGroups get_session_id get_session_replay_url opt_in_capturing opt_out_capturing has_opted_in_capturing has_opted_out_capturing get_explicit_consent_status is_capturing clear_opt_in_out_capturing debug'.split(' '); 654 655 for (var i = 0; i < methods.length; i++) { 656 bind(instance, methods[i]); 657 } 658 659 posthog._i.push([apiKey, options, name]); 660 }; 661 662 posthog.__SV = 1; 663 w.posthog = posthog; 664 } 665 666 /* 667 * Host relativo ("/relay") vira absoluto na origem da propria pagina. 668 * E o modo de ligar o relay first-party sem fixar dominio na configuracao: 669 * o mesmo "/relay" vale para www.looke.com.br, homolog e localhost. 670 */
671 function resolveConfiguredHost(value) { 672 var host = String(value || '').replace(/\/$/, ''); 673 674 if (host.charAt(0) === '/') { 675 return w.location.origin + host; 676 } 677 678 return host; 679 } 680 681 function resolvePostHogAssetHost(options) { 682 var configuredAssetHost = cfg.posthog && cfg.posthog.assetHost; 683 if (configuredAssetHost) { 684 return resolveConfiguredHost(configuredAssetHost); 685 } 686 687 var apiHost = options && options.api_host ? options.api_host : 'https://us.i.posthog.com'; 688 return String(apiHost).replace('.i.posthog.com', '-assets.i.posthog.com').replace(/\/$/, ''); 689 } 690 691 function buildPostHogOptions() { 692 // recordHeaders/recordBody fixados como falso: payload de rede fora da 693 // gravacao. O numero do cartao trafega no corpo dos POSTs de /Payment 694 // (GetCardPromotionIfAvailable e os formularios de assinatura/compra). 695 // No SDK, falso no cliente vence a configuracao remota do projeto. 696 var sessionRecording = { 697 maskAllInputs: true, 698 recordHeaders: false, 699 recordBody: false 700 }; 701 702 var mask = selectorList(cfg.maskSelectors); 703 if (mask) { sessionRecording.maskTextSelector = mask; } 704 705 var block = selectorList(cfg.blockSelectors); 706 if (block) { sessionRecording.blockSelector = block; } 707 708 var apiHost = resolveConfiguredHost(cfg.posthog.host) || 'https://us.i.posthog.com'; 709 710 var options = { 711 api_host: apiHost, 712 defaults: '2026-05-30', 713 debug: !!cfg.debug, 714 person_profiles: 'identified_only', 715 capture_pageview: true, 716 // Autocapture nao envia o texto do elemento clicado: titular e numero 717 // do cartao aparecem como texto puro nas telas de assinatura. 718 mask_all_text: true, 719 session_recording: sessionRecording, 720 before_send: function (event) { 721 if (!event) { return event; } 722 723 if (event.properties) { event.properties = sanitizeProperties(event.properties, { preservePostHogInternals: true }); } 724 if (event.$set) { event.$set = sanitizeProperties(event.$set); } 725 if (event.$set_once) { event.$set_once = sanitizeProperties(event.$set_once); } 726 727 if (event.properties && event.properties.$current_url) { 728 event.properties.$current_url = sanitizeUrl(event.properties.$current_url); 729 } 730 731 if (event.properties && event.properties.$referrer) { 732 event.properties.$referrer = sanitizeUrl(event.properties.$referrer); 733 } 734 735 return event; 736 }, 737 loaded: function () { 738 ready.posthog = true; 739 log('posthog carregado'); 740 741 try { 742 if (w.posthog && w.posthog.capture) { 743 w.posthog.capture('looke_session_replay_loaded', { 744 provider: cfg.provider || null, 745 clarity_enabled: !!(cfg.clarity && cfg.clarity.projectId), 746 posthog_project_id: cfg.posthog ? cfg.posthog.projectId : null, 747 current_url: sanitizeUrl(w.location.href) 748 }); 749 } 750 } catch (e) { 751 log('posthog evento de carregamento falhou', e); 752 } 753 754 try { 755 if (w.posthog && w.posthog.startSessionRecording) { 756 w.posthog.startSessionRecording(); 757 schedulePostHogRecordingLimit(); 758 } 759 } catch (e) { 760 log('posthog startSessionRecording falhou', e); 761 } 762 763 drain(); 764 crossLink(); 765 } 766 }; 767 768 // Atras do relay o api_host nao e mais *.posthog.com; o ui_host mantem 769 // os links de replay e o toolbar apontando para o painel de verdade.
770 if (apiHost.indexOf('.posthog.com') < 0) { 771 options.ui_host = 'https://us.posthog.com'; 772 } 773 774 return options; 775 } 776 777 function isReady(driver) { 778 return ready[driver.name] === true; 779 } 780 781 function call(driver, method, args) { 782 try { 783 if (typeof driver[method] === 'function') { 784 driver[method].apply(driver, args); 785 } 786 } catch (e) { 787 log(method + ' falhou em ' + driver.name, e); 788 } 789 } 790 791 function dispatch(method, args) { 792 for (var i = 0; i < active.length; i++) { 793 var driver = active[i]; 794 795 if (isReady(driver)) { 796 call(driver, method, args); 797 } else { 798 pending.push({ driver: driver.name, method: method, args: args }); 799 } 800 } 801 } 802 803 function drain() { 804 var queued = pending; 805 pending = []; 806 807 for (var i = 0; i < queued.length; i++) { 808 var item = queued[i]; 809 var driver = DRIVERS[item.driver]; 810 811 if (driver && isReady(driver)) { 812 call(driver, item.method, item.args); 813 } else { 814 pending.push(item); 815 } 816 } 817 } 818 819 function crossLink() { 820 if (linked || !ready.clarity || !ready.posthog || !w.clarity || !w.posthog) { return; } 821 822 try { 823 var sessionId = w.posthog.get_session_id ? w.posthog.get_session_id() : null; 824 if (sessionId) { w.clarity('set', 'posthog_session_id', String(sessionId)); } 825 826 var replayUrl = DRIVERS.posthog.sessionUrl(); 827 if (replayUrl) { w.clarity('set', 'posthog_replay_url', String(replayUrl)); } 828 829 w.posthog.register({ clarity_project_id: cfg.clarity ? cfg.clarity.projectId : null }); 830 831 linked = true; 832 } catch (e) { 833 log('cross-link falhou', e); 834 } 835 } 836 837 function start() { 838 if (started) { return; } 839 if (!hasConsent()) { 840 log('aguardando consentimento'); 841 return; 842 } 843 844 watchDynamicDom(); 845 watchPlayerEvents(); 846 847 for (var name in DRIVERS) { 848 if (Object.prototype.hasOwnProperty.call(DRIVERS, name) && DRIVERS[name].enabled()) { 849 active.push(DRIVERS[name]); 850 } 851 } 852 853 if (!active.length) { 854 log('nenhum provider selecionado no sorteio', roll); 855 started = true; 856 return; 857 } 858 859 started = true; 860 861 for (var i = 0; i < active.length; i++) { 862 call(active[i], 'load', []); 863 } 864 865 if (cfg.user && cfg.user.distinctId) { 866 SessionReplay.identify(cfg.user); 867 } 868 869 drain(); 870 crossLink(); 871 } 872 873 var SessionReplay = { 874 identify: function (user) { 875 dispatch('identify', [user || cfg.user]); 876 }, 877 878 track: function (name, props) { 879 dispatch('track', [name, props]); 880 }, 881 882 tag: function (key, value) { 883 dispatch('tag', [key, value]); 884 }, 885 886 upgrade: function (reason) { 887 dispatch('upgrade', [reason]); 888 }, 889 890 startAfterConsent: function () { 891 storageSet(w.localStorage, CONSENT_KEY, 'true'); 892 start(); 893 }, 894 895 status: function () { 896 return { 897 roll: roll, 898 started: started, 899 requireConsent: !!cfg.requireConsent, 900 hasConsent: hasConsent(), 901 posthogMaxRecordingSeconds: getPostHogMaxRecordingSeconds(), 902 clarity: ready.clarity, 903 posthog: ready.posthog 904 }; 905 }, 906 907 getSessionUrls: function () { 908 var urls = {}; 909 910 for (var i = 0; i < active.length; i++) { 911 if (isReady(active[i])) { 912 urls[active[i].name] = active[i].sessionUrl(); 913 } 914 } 915 916 return urls; 917 } 918 }; 919 920 w.SessionReplay = SessionReplay; 921 922 start(); 923})(window, document);
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.