cdp-edge 2.3.9 → 2.5.1
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.
- package/README.md +33 -3
- package/bin/cdp-edge.js +3 -2
- package/dist/commands/validate.js +248 -84
- package/dist/sdk/cdpTrack.js +2095 -0
- package/dist/sdk/cdpTrack.min.js +64 -0
- package/dist/sdk/install-snippet.html +10 -0
- package/extracted-skill/tracking-events-generator/anti-blocking.js +1 -1
- package/extracted-skill/tracking-events-generator/cdpTrack.js +0 -10
- package/extracted-skill/tracking-events-generator/engagement-scoring.js +2 -2
- package/extracted-skill/tracking-events-generator/micro-events.js +1 -1
- package/extracted-skill/tracking-events-generator/tracking.config.js +3 -3
- package/package.json +5 -1
- package/scripts/build-sdk.js +106 -0
- package/server-edge-tracker/index.ts +93 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* CDP Edge SDK v2.5.1
|
|
3
|
+
* (c) 2026 CDP Edge — Quantum Tracking
|
|
4
|
+
* Gerado em: 2026-04-15T01:32:42.616Z
|
|
5
|
+
* Endpoint padrão: /track (mesmo domínio — anti-adblock)
|
|
6
|
+
*/
|
|
7
|
+
"use strict";var cdpTrack=(()=>{var V=Object.defineProperty;var ve=Object.getOwnPropertyDescriptor;var ye=Object.getOwnPropertyNames;var we=Object.prototype.hasOwnProperty;var Te=(t,e)=>()=>(t&&(e=t(t=0)),e);var q=(t,e)=>{for(var n in e)V(t,n,{get:e[n],enumerable:!0})},Se=(t,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of ye(e))!we.call(t,r)&&r!==n&&V(t,r,{get:()=>e[r],enumerable:!(o=ve(e,r))||o.enumerable});return t};var be=t=>Se(V({},"__esModule",{value:!0}),t);var re={};q(re,{default:()=>at});var oe,at,ie=Te(()=>{"use strict";oe={config:{rageClickThreshold:3,rageClickTime:700,idleThreshold:6e4,scoreThresholds:{engaged:40,highIntent:80}},state:{clickHistory:[],startTime:Date.now(),lastActivity:Date.now(),lastPulse:Date.now(),isIdle:!1,formStartTime:{},userScore:0,firedScoreEvents:new Set,abVariant:null},init(){this.setupRageClicks(),this.setupVisibility(),this.setupHeartbeat(),this.setupScroll(),this.setupVideoTracking(),this.setupFormAnalytics(),this.setupFormAbandonment(),this.setupCopyPaste(),this.setupExitIntent(),this.setupOutboundLinks(),this.setupErrorTracking(),this.setupIdleDetection(),this.setupScoring(),this.setupABTesting(),console.log("[CDP Edge] Enterprise Behavior Engine Initialized")},setupABTesting(){let t=o=>{let i=`; ${document.cookie}`.split(`; ${o}=`);if(i.length===2)return i.pop().split(";").shift()},e=new URLSearchParams(window.location.search);this.state.abVariant=e.get("cdp_variant")||t("cdp_ab_variant")||"original",console.log(`[CDP Edge] A/B Variant Detected: ${this.state.abVariant}`);let n=cdpTrack.track;cdpTrack.track=(o,r={})=>{let i={...r,ab_test_variant:this.state.abVariant,user_score:this.state.userScore};return n.apply(cdpTrack,[o,i])}},setupScoring(){console.log("[CDP Edge] Scoring Engine Online")},addScore(t,e){this.state.userScore=Math.min(100,Math.max(0,this.state.userScore+t)),console.log(`[CDP Edge] Score Update: +${t} (${e}) | Total: ${this.state.userScore}`),this.state.userScore>=this.config.scoreThresholds.highIntent&&!this.state.firedScoreEvents.has("highIntent")?(this.state.firedScoreEvents.add("highIntent"),cdpTrack.track("High_Intent_Lead",{score:this.state.userScore,meta_intensity:"high"})):this.state.userScore>=this.config.scoreThresholds.engaged&&!this.state.firedScoreEvents.has("engaged")&&(this.state.firedScoreEvents.add("engaged"),cdpTrack.track("Engaged_User",{score:this.state.userScore,meta_intensity:"medium"}))},setupRageClicks(){document.addEventListener("click",t=>{let e=Date.now();this.state.clickHistory.push(e),this.state.clickHistory=this.state.clickHistory.filter(n=>e-n<this.config.rageClickTime),this.state.clickHistory.length>=this.config.rageClickThreshold&&(cdpTrack.track("rage_click",{element_id:t.target.id||"",element_class:t.target.className||"",x:t.pageX,y:t.pageY,meta_intensity:"low"}),this.addScore(-10,"rage_click"),this.state.clickHistory=[])})},setupScroll(){let t=[25,50,75,90],e=new Set;window.addEventListener("scroll",()=>{let n=Math.round(window.scrollY/(document.documentElement.scrollHeight-window.innerHeight)*100);t.forEach(o=>{n>=o&&!e.has(o)&&(e.add(o),this.addScore(o===25||o===50?5:10,`scroll_${o}%`),cdpTrack.track("scroll_depth",{percent:o,meta_intensity:o>=50?"medium":"low"}))})},{passive:!0})},setupVisibility(){document.addEventListener("visibilitychange",()=>{let t=document.visibilityState;cdpTrack.track("tab_visibility_change",{status:t,time_since_start:Math.floor((Date.now()-this.state.startTime)/1e3),meta_intensity:t==="visible"?"high":"low"})})},setupHeatmap(){document.addEventListener("click",t=>{typeof cdpTrack.sendServerEvent=="function"&&cdpTrack.sendServerEvent("click_heatmap",null,{x:t.pageX,y:t.pageY,element:t.target.tagName.toLowerCase(),id:t.target.id||"",classes:t.target.className||""})})},setupHeartbeat(){setInterval(()=>{let t=Math.floor((Date.now()-this.state.startTime)/1e3);cdpTrack.track("pulse_heartbeat",{duration_seconds:t,is_visible:document.visibilityState==="visible"})},this.config.heartbeatInterval)},setupVideoTracking(){let t=document.querySelectorAll("iframe"),e=new Set;t.forEach(n=>{let o=n.src||"",r=o.includes("youtube.com/embed"),i=o.includes("vimeo.com/video");if((r||i)&&(window.addEventListener("message",s=>{try{let a=typeof s.data=="string"?JSON.parse(s.data):s.data;r&&a.event==="infoDelivery"&&a.info&&a.info.currentTime&&this.handleVideoProgress(n,a.info.currentTime,a.info.duration,e,"YouTube"),i&&a.event==="timeupdate"&&this.handleVideoProgress(n,a.data.seconds,a.data.duration,e,"Vimeo")}catch(a){}}),r&&!o.includes("enablejsapi=1"))){let s=new URL(o);s.searchParams.set("enablejsapi","1"),n.src=s.toString()}})},handleVideoProgress(t,e,n,o,r){if(!n)return;let i=Math.floor(e/n*100),s=[25,50,75,100],a=t.id||t.src.split("/").pop().split("?")[0];s.forEach(u=>{let m=`${a}_${u}`;i>=u&&!o.has(m)&&(o.add(m),this.addScore(u===25?10:u===50?15:25,`vsl_${u}%`),cdpTrack.track("video_milestone",{video_id:a,platform:r,percent:u,meta_intensity:u>=50?"high":"medium"}))})},setupFormAnalytics(){document.querySelectorAll("input, select, textarea").forEach(e=>{e.addEventListener("focus",()=>{let n=e.name||e.id;this.state.formStartTime[n]||(this.state.formStartTime[n]=Date.now(),this.addScore(10,`form_interaction_${n}`),cdpTrack.track("form_field_focus",{field:n}))}),e.addEventListener("blur",()=>{let n=e.name||e.id,o=Math.round((Date.now()-this.state.formStartTime[n])/1e3);o>0&&cdpTrack.track("form_field_blur",{field:n,duration_sec:o})})})},setupFormAbandonment(){let t=new Set,e=!1;document.addEventListener("focusin",n=>{let o=n.target;if(o.tagName==="INPUT"||o.tagName==="TEXTAREA"||o.tagName==="SELECT"){let r=o.name||o.id||o.type;r&&t.add(r)}},!0),document.addEventListener("submit",()=>{e=!0},!0),document.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&t.size>0&&!e&&(this.addScore(-5,"form_abandonment"),cdpTrack.track("form_abandonment",{fields_interacted:Array.from(t),fields_count:t.size,meta_intensity:"medium",time_on_page:Math.floor((Date.now()-this.state.startTime)/1e3)}))}),window.addEventListener("beforeunload",()=>{if(t.size>0&&!e&&navigator.sendBeacon&&typeof cdpTrack!="undefined"){let n=JSON.stringify({eventName:"form_abandonment",behavioral_data:{user_score:this.state.userScore},fields_interacted:Array.from(t),fields_count:t.size,meta_intensity:"medium"});navigator.sendBeacon("/api/tracking",new Blob([n],{type:"application/json"}))}})},setupExitIntent(){let t=!1;document.addEventListener("mousemove",n=>{n.clientY<20&&!t&&(t=!0,this.addScore(15,"exit_intent"),cdpTrack.track("exit_intent",{mouse_y:n.clientY,time_on_page:Math.floor((Date.now()-this.state.startTime)/1e3),user_score:this.state.userScore,meta_intensity:"high"}),setTimeout(()=>{t=!1},3e4))},{passive:!0});let e=!1;document.addEventListener("visibilitychange",()=>{if(document.visibilityState==="hidden"&&!e){let n=Math.floor((Date.now()-this.state.startTime)/1e3);n>5&&(e=!0,cdpTrack.track("exit_intent_mobile",{time_on_page:n,user_score:this.state.userScore,meta_intensity:"medium"}))}})},setupCopyPaste(){document.addEventListener("copy",()=>{let t=window.getSelection().toString();t.length>0&&(this.addScore(20,"text_copy"),cdpTrack.track("content_copy",{text_length:t.length,meta_intensity:"medium"}))})},setupOutboundLinks(){document.addEventListener("click",t=>{let e=t.target.closest("a");if(e&&e.href){let n=e.href,o=!n.includes(window.location.hostname),r=n.includes("wa.me")||n.includes("hotmart.com")||n.includes("kiwify.com")||n.includes("checkout");o&&r&&(this.addScore(100,"outbound_conversion_intent"),cdpTrack.track("outbound_click",{destination:n,meta_intensity:"high"}))}})},setupErrorTracking(){window.addEventListener("error",t=>{typeof cdpTrack.sendServerEvent=="function"&&cdpTrack.sendServerEvent("js_error",null,{message:t.message,source:t.filename,lineno:t.lineno,colno:t.colno})})},setupIdleDetection(){["mousedown","mousemove","keydown","scroll","touchstart"].forEach(e=>{document.addEventListener(e,()=>{this.state.lastActivity=Date.now(),this.state.isIdle&&(this.state.isIdle=!1,cdpTrack.track("user_active",{status:"back_online"}))},{passive:!0})}),setInterval(()=>{Date.now()-this.state.lastActivity>this.config.idleThreshold&&!this.state.isIdle&&(this.state.isIdle=!0,cdpTrack.track("user_idle",{idle_duration:this.config.idleThreshold/1e3}))},1e4)}};typeof cdpTrack!="undefined"&&oe.init();at=oe});var yt={};q(yt,{generateId:()=>ce,getSessionId:()=>U,getUTMs:()=>A,getUTMsWithFallback:()=>de,getUserId:()=>B,getUserIdWithFallback:()=>ue,init:()=>he,passCheckoutParams:()=>le,setupAutoFormCapture:()=>ge,track:()=>D,trackAddToCart:()=>fe,trackLead:()=>G,trackPurchase:()=>me,trackViewContent:()=>pe,updateConsent:()=>se});var Ee={endpoint:"/track",platforms:["hotmart","kiwify","eduzz","monetizze","cartpanda","ticto"],siteDomain:"",debug:!1,consent:{defaultDenied:!0,urlPassthrough:!0,waitForUpdate:500},autoCaptureForms:!0,passCheckoutParams:!0,initBehaviorEngine:!0},h=Ee;var P=typeof window!="undefined";var H={thresholds:[25,50,75,100],signalStrength:{"25%":1.5,"50%":2,"75%":3,"100%":4}},L={thresholds:{curioso:1e4,interessado:6e4,comprador:18e4,profundao:60},signalStrength:{curioso:1,interessado:2.5,comprador:4,profundao:3.5},intentionLevels:{curioso:"curioso",interessado:"interessado",comprador:"comprador",profundao:"profundo"}},f={progressThresholds:[25,50,75,100],dropoutEnabled:!0,signalStrength:{play:2,progress25:3,progress50:4,progress75:5,complete:5,pause:1,resume:1.5,seek:.5,dropout:2.5}},x={maxRapidClicks:3,rapidClickWindow:1e3,clickCategories:["button","link","input","cta","price","generic"],signalStrength:{button:2,link:1.5,cta:2.5,input:1,price:2,generic:.5}},J={minHoverTimeForSignal:3e3,maxHoverTime:3e4,signalStrength:3},c={pageLoadTime:Date.now(),scrollTracking:{lastScrollPercent:0,trackedThresholds:new Set},timeTracking:{lastCheckTime:Date.now(),currentLevel:"curioso",timeOnPage:0},videoTracking:{},videoSummary:{totalVideos:0,startedCount:0,completedCount:0,maxProgress:0},clickTracking:{clicks:[],lastClickTime:0,rapidClickDetected:!1},ctaHoverTracking:{hoverStartTime:null,hoveredElement:null}};function Ce(){if(!P)return;new IntersectionObserver(e=>{e.forEach(n=>{if(!n.isIntersecting)return;let o=Math.round((window.scrollY+window.innerHeight)/document.body.scrollHeight*100);H.thresholds.forEach(r=>{let i=`scroll_${r}`;if(o>=r&&!c.scrollTracking.trackedThresholds.has(i)){let s=H.signalStrength[`${r}%`]||0;p("Scroll",{scroll_depth:r,scroll_percent:o,signal_strength:s,engagement_type:"scroll",time_on_page:Math.round((Date.now()-c.pageLoadTime)/1e3)}),c.scrollTracking.trackedThresholds.add(i)}})})},{threshold:H.thresholds.map(e=>e/100)}).observe(document.body)}function xe(){P&&setInterval(()=>{let t=Date.now()-c.pageLoadTime,e=Math.round(t/1e3),n=c.timeTracking.currentLevel,o=c.timeTracking.currentLevel;e>=L.thresholds.comprador?(n="comprador",o=L.signalStrength.comprador):e>=L.thresholds.interessado?(n="interessado",o=L.signalStrength.interessado):e>=L.thresholds.curioso&&(n="curioso",o=L.signalStrength.curioso),n!==c.timeTracking.currentLevel&&(c.timeTracking.currentLevel=n,p("TimeOnPage",{time_on_page:e,intention_level:n,signal_strength:o,engagement_type:"time",previous_level:c.timeTracking.previousLevel}),c.timeTracking.previousLevel=n)},5e3)}function Le(){return{playTime:0,totalWatchTime:0,lastProgress:-1,lastSecond:0,started:!1,paused:!1,completed:!1,dropoutPercent:null,dropoutSecond:null}}function E(t){let e=c.videoTracking[t],n=c.videoSummary;n.totalVideos=Object.keys(c.videoTracking).length,n.startedCount=Object.values(c.videoTracking).filter(o=>o.started).length,n.completedCount=Object.values(c.videoTracking).filter(o=>o.completed).length,n.maxProgress=Math.max(...Object.values(c.videoTracking).map(o=>o.lastProgress<0?0:o.lastProgress))}function z(t,e,n){let o=c.videoTracking[t];!o||o.completed||(o.dropoutPercent=e,o.dropoutSecond=n,f.dropoutEnabled&&p("VideoDropout",{video_id:t,dropout_percent:e,dropout_second:n,engagement_score:f.signalStrength.dropout,engagement_type:"video",video_summary:{...c.videoSummary}}))}function Pe(){if(!P)return;document.querySelectorAll('video, iframe[src*="youtube"], iframe[src*="vimeo"]').forEach((e,n)=>{let o=e.id||e.getAttribute("data-video-id")||`video_${n}`;if(c.videoTracking[o]=Le(),E(o),e.tagName==="IFRAME"&&e.src.includes("youtube")){De(e,o);return}if(e.tagName==="IFRAME"&&e.src.includes("vimeo")){Ae(e,o);return}Ie(e,o)}),window.addEventListener("beforeunload",()=>{Object.entries(c.videoTracking).forEach(([e,n])=>{n.started&&!n.completed&&z(e,n.lastProgress<0?0:n.lastProgress,n.lastSecond)})})}function Ie(t,e){let n=()=>c.videoTracking[e];t.addEventListener("play",()=>{n().started=!0,n().paused=!1,n().playTime||(n().playTime=Date.now()),E(e),p("VideoPlay",{video_id:e,video_platform:"html5",progress_percent:M(t),engagement_score:f.signalStrength.play,engagement_type:"video"})}),t.addEventListener("pause",()=>{n().paused=!0;let o=M(t),r=Math.round(t.currentTime);p("VideoPause",{video_id:e,video_platform:"html5",progress_percent:o,pause_second:r,engagement_score:f.signalStrength.pause,engagement_type:"video"}),z(e,o,r)}),t.addEventListener("play",()=>{n().dropoutPercent=null,n().dropoutSecond=null}),t.addEventListener("seeked",()=>{p("VideoSeek",{video_id:e,video_platform:"html5",progress_percent:M(t),seek_to_second:Math.round(t.currentTime),engagement_score:f.signalStrength.seek,engagement_type:"video"})}),t.addEventListener("timeupdate",()=>{if(t.paused||t.ended)return;let o=M(t),r=Math.round(t.currentTime);n().lastSecond=r,f.progressThresholds.forEach(i=>{o>=i&&n().lastProgress<i&&(n().lastProgress=i,p("VideoProgress",{video_id:e,video_platform:"html5",progress_percent:i,progress_second:r,engagement_score:f.signalStrength[`progress${i}`]||0,engagement_type:"video",video_summary:{...c.videoSummary}}),E(e))})}),t.addEventListener("ended",()=>{n().paused=!1,n().completed=!0,n().dropoutPercent=null,n().dropoutSecond=null;let o=n().playTime?Math.round((Date.now()-n().playTime)/1e3):0;E(e),p("VideoComplete",{video_id:e,video_platform:"html5",progress_percent:100,total_watch_time:o,engagement_score:f.signalStrength.complete,engagement_type:"video",video_summary:{...c.videoSummary}})})}function M(t){return!t.duration||t.duration===0?0:Math.round(t.currentTime/t.duration*100)}function De(t,e){try{let o=new URL(t.src);o.searchParams.get("enablejsapi")||(o.searchParams.set("enablejsapi","1"),t.src=o.toString())}catch(o){}if(!window._ytApiLoading){window._ytApiLoading=!0;let o=document.createElement("script");o.src="https://www.youtube.com/iframe_api",document.head.appendChild(o)}let n=()=>{if(typeof YT=="undefined"||!YT.Player){setTimeout(n,300);return}let o=()=>c.videoTracking[e],r=null;new YT.Player(t,{events:{onStateChange:i=>{let s=YT.PlayerState,a=i.target,u=a.getDuration()||0,m=a.getCurrentTime()||0,l=u>0?Math.round(m/u*100):0,g=Math.round(m);if(i.data===s.PLAYING)o().started=!0,o().paused=!1,o().playTime||(o().playTime=Date.now()),o().dropoutPercent=null,o().dropoutSecond=null,E(e),p("VideoPlay",{video_id:e,video_platform:"youtube",progress_percent:l,engagement_score:f.signalStrength.play,engagement_type:"video"}),clearInterval(r),r=setInterval(()=>{if(!a||typeof a.getPlayerState!="function"||a.getPlayerState()!==s.PLAYING)return;let d=a.getCurrentTime()||0,k=a.getDuration()||0,y=k>0?Math.round(d/k*100):0;o().lastSecond=Math.round(d),f.progressThresholds.forEach(b=>{y>=b&&o().lastProgress<b&&(o().lastProgress=b,p("VideoProgress",{video_id:e,video_platform:"youtube",progress_percent:b,progress_second:Math.round(d),engagement_score:f.signalStrength[`progress${b}`]||0,engagement_type:"video",video_summary:{...c.videoSummary}}),E(e))})},2e3);else if(i.data===s.PAUSED)clearInterval(r),o().paused=!0,p("VideoPause",{video_id:e,video_platform:"youtube",progress_percent:l,pause_second:g,engagement_score:f.signalStrength.pause,engagement_type:"video"}),z(e,l,g);else if(i.data===s.ENDED){clearInterval(r),o().completed=!0,o().dropoutPercent=null,o().dropoutSecond=null;let d=o().playTime?Math.round((Date.now()-o().playTime)/1e3):0;E(e),p("VideoComplete",{video_id:e,video_platform:"youtube",progress_percent:100,total_watch_time:d,engagement_score:f.signalStrength.complete,engagement_type:"video",video_summary:{...c.videoSummary}})}}}})};if(typeof YT!="undefined"&&YT.Player)n();else{let o=window.onYouTubeIframeAPIReady;window.onYouTubeIframeAPIReady=()=>{o&&o(),n()}}}function Ae(t,e){let n=()=>c.videoTracking[e],o=0,r=(s,a)=>{t.contentWindow.postMessage(JSON.stringify({method:s,value:a}),"https://player.vimeo.com")},i=()=>{["play","pause","ended","timeupdate","seeked"].forEach(s=>{r("addEventListener",s)}),r("getDuration")};window.addEventListener("message",s=>{var g;if(!s.origin.includes("vimeo.com"))return;let a;try{a=JSON.parse(s.data)}catch(d){return}if(!a||a.player_id!==t.id)return;if(a.event==="ready"){i();return}if(a.method==="getDuration"){o=a.value||0;return}let u=((g=a.data)==null?void 0:g.seconds)||0,m=o>0?Math.round(u/o*100):0,l=Math.round(u);if(a.event==="play")n().started=!0,n().paused=!1,n().playTime||(n().playTime=Date.now()),n().dropoutPercent=null,n().dropoutSecond=null,E(e),p("VideoPlay",{video_id:e,video_platform:"vimeo",progress_percent:m,engagement_score:f.signalStrength.play,engagement_type:"video"});else if(a.event==="pause")n().paused=!0,n().lastSecond=l,p("VideoPause",{video_id:e,video_platform:"vimeo",progress_percent:m,pause_second:l,engagement_score:f.signalStrength.pause,engagement_type:"video"}),z(e,m,l);else if(a.event==="timeupdate")n().lastSecond=l,f.progressThresholds.forEach(d=>{m>=d&&n().lastProgress<d&&(n().lastProgress=d,p("VideoProgress",{video_id:e,video_platform:"vimeo",progress_percent:d,progress_second:l,engagement_score:f.signalStrength[`progress${d}`]||0,engagement_type:"video",video_summary:{...c.videoSummary}}),E(e))});else if(a.event==="ended"){n().completed=!0,n().dropoutPercent=null,n().dropoutSecond=null;let d=n().playTime?Math.round((Date.now()-n().playTime)/1e3):0;E(e),p("VideoComplete",{video_id:e,video_platform:"vimeo",progress_percent:100,total_watch_time:d,engagement_score:f.signalStrength.complete,engagement_type:"video",video_summary:{...c.videoSummary}})}else a.event==="seeked"&&p("VideoSeek",{video_id:e,video_platform:"vimeo",progress_percent:m,seek_to_second:l,engagement_score:f.signalStrength.seek,engagement_type:"video"})}),t.contentDocument?i():t.addEventListener("load",i)}function Me(){P&&document.addEventListener("click",t=>{let e=t.target,n=ze(e),o=Ne(t),r=Math.round((Date.now()-c.pageLoadTime)/1e3),i=Date.now();i-c.clickTracking.lastClickTime<x.rapidClickWindow&&c.clickTracking.clicks.push({time:i,target:e}),setTimeout(()=>{let a=c.clickTracking.clicks.filter(u=>i-u.time<x.rapidClickWindow);a.length>=x.maxRapidClicks?(c.clickTracking.rapidClickDetected=!0,p("RapidClicks",{click_count:a.length,time_window:x.rapidClickWindow,behavior:"nervous",engagement_score:3,engagement_type:"clicks",time_on_page:r,description:`Usu\xE1rio clicou ${a.length} vezes em ${x.rapidClickWindow/1e3} segundos`})):(c.clickTracking.rapidClickDetected=!1,c.clickTracking.clicks=[])},x.rapidClickWindow),c.clickTracking.lastClickTime=i,p("Click",{click_category:n,target_info:Oe(e),position:o,time_on_page:r,click_heatmap:!0,engagement_score:$e(n,o),engagement_type:"clicks"})},!0)}function ze(t){let e=o=>t.closest(o),n=t.className||"";return e("button")||n.includes("btn")?"button":e("a")?"link":e("input")?"input":e(".cta")||n.includes("cta")?"cta":e(".price")||n.includes("price")?"price":e(".whatsapp")||n.includes("whatsapp")?"whatsapp":e(".email")||n.includes("email")?"email":e(".phone")||n.includes("phone")?"phone":"generic"}function Ne(t){return{x:Math.round(t.clientX),y:Math.round(t.clientY),relativeX:Math.round(t.clientX/window.innerWidth*100),relativeY:Math.round(t.clientY/window.innerHeight*100),viewportWidth:window.innerWidth,viewportHeight:window.innerHeight}}function Oe(t){var e;return{tag:t.tagName,class:t.className,id:t.id,text:((e=t.textContent)==null?void 0:e.substring(0,30))||"",attributes:Array.from(t.attributes).map(n=>`${n.name}="${n.value}"`).join(" ")}}function $e(t,e){let n=x.signalStrength[t]||.5,o=Math.min(e.timeOnPage/60,2),r=Math.min(e.scrollDepth/100,.5);return n+o+r}function Be(){if(!P)return;['a[href*="checkout"]','a[href*="comprar"]',"button.cta",".btn-comprar",".btn-checkout",".cta-button",'[data-cta="true"]','button[type="submit"]'].forEach(e=>{document.querySelectorAll(e).forEach(n=>{n.addEventListener("mouseenter",o=>{o.target.closest(e)&&(c.ctaHoverTracking.hoverStartTime=Date.now(),c.ctaHoverTracking.hoveredElement=e)}),n.addEventListener("mouseleave",()=>{if(c.ctaHoverTracking.hoverStartTime){let o=Date.now()-c.ctaHoverTracking.hoverStartTime;o>=J.minHoverTimeForSignal&&p("CTAHover",{cta_selector:e,hover_time_seconds:Math.round(o/1e3),engagement_score:J.signalStrength,engagement_type:"hover",time_on_page:Math.round((Date.now()-c.pageLoadTime)/1e3)})}c.ctaHoverTracking.hoverStartTime=null,c.ctaHoverTracking.hoveredElement=null})})})}function p(t,e={}){typeof cdpTrack!="undefined"&&cdpTrack.track?cdpTrack.track(t,e):console.warn("cdpTrack n\xE3o dispon\xEDvel - evento n\xE3o enviado:",t,e)}function K(){P&&(c.pageLoadTime=Date.now(),Ce(),xe(),Pe(),Me(),Be(),console.log("\u2705 Micro-Events inicializados"))}var T={timeWeights:{curioso:1,interessado:2.5,comprador:4},scrollWeights:{baixo:1,medio:2,alto:3},clickWeights:{generico:1,cta:2.5,button:2,link:1.5,input:.5},videoWeights:{play:1.5,progress25:2,progress50:3,progress75:4,complete:5},hoverWeights:{curto:1,medio:2,longo:3}},v={timeOnPage:0,scrollDepth:0,clicksCount:0,videoEngagement:0,ctaHoverTime:0,lastActivityTime:Date.now()};function Ve(t){let e="curioso",n=T.timeWeights.curioso;return t>=10&&t<60?(e="interessado",n=T.timeWeights.interessado):t>=60&&(e="comprador",n=T.timeWeights.comprador),{score:n,level:e}}function He(t){let e="baixo",n=T.scrollWeights.baixo;return t>=25&&t<75?(e="medio",n=T.scrollWeights.medio):t>=75&&(e="alto",n=T.scrollWeights.alto),{score:n,level:e}}function Fe(t,e){let n=T.clickWeights.generico,o=T.clickWeights[e]||1,r=Math.max(0,1-t/50);return n+o}function je(t){let e="curto",n=T.hoverWeights.curto;return t>=3&&t<10?(e="medio",n=T.hoverWeights.medio):t>=10&&(e="longo",n=T.hoverWeights.longo),{score:n,level:e}}function X(){let{score:t,level:e}=Ve(v.timeOnPage),{score:n}=He(v.scrollDepth),o=v.clicksCount>0?Fe(v.clicksCount,"generico"):0,r=v.videoEngagement,i=v.ctaHoverTime>0?je(v.ctaHoverTime/1e3):0,s=t*.3+n*.2+o*.15+r*.25+i*.1,a=e;return s<1.5?a="curioso":s<2.5?a="interessado":a="comprador",{totalScore:Math.min(s,5),timeScore:t,scrollScore:n,clickScore:o,videoScore:r,hoverScore:i,intentionLevel:a,components:{timeOnPage:v.timeOnPage,scrollDepth:v.scrollDepth,clicksCount:v.clicksCount,videoEngagement:v.videoEngagement,ctaHoverTime:v.ctaHoverTime}}}function F(t,e){v[t]=e,v.lastActivityTime=Date.now()}var O={email:{trim:!0,lowercase:!0,removeDots:!1,removePlus:!0},phone:{keepOnlyDigits:!0,addCountryCode:!0,defaultCountryCode:"55"},name:{trim:!0,lowercase:!0,removeAccents:!0,removeExtraSpaces:!0,maxLength:100},city:{trim:!0,lowercase:!0,removeAccents:!0,maxLength:50},state:{trim:!0,lowercase:!0,removeAccents:!0,maxLength:50},zip:{trim:!0,keepOnlyDigits:!0,maxLength:10}};function We(t){if(!t||typeof t!="string")return"";let e=t.trim();return e.includes("@gmail.com")&&(e=e.split("+")[0]+"@gmail.com"),e.includes("@googlemail.com")&&(e=e.split("+")[0]+"@googlemail.com"),e.toLowerCase()}function Re(t){if(!t||typeof t!="string")return"";let e=t.replace(/\D/g,"");return(e.length===11||e.length===10)&&(e="55"+e),e.substring(0,15)}function N(t){if(!t||typeof t!="string")return"";let e=t.trim();return e=e.normalize("NFD").replace(/[\u0300-\u036f]/g,""),e=e.toLowerCase(),e=e.replace(/\s+/g," "),e.substring(0,O.name.maxLength)}function Ue(t){if(!t||typeof t!="string")return"";let e=t.trim();return e=e.normalize("NFD").replace(/[\u0300-\u036f]/g,""),e=e.toLowerCase(),e=e.replace(/\s+/g," "),e.substring(0,O.city.maxLength)}function Ye(t){if(!t||typeof t!="string")return"";let e=t.trim();return e=e.normalize("NFD").replace(/[\u0300-\u036f]/g,""),e=e.toLowerCase(),e.substring(0,O.state.maxLength)}function Ge(t){return!t||typeof t!="string"?"":t.replace(/\D/g,"").substring(0,O.zip.maxLength)}function qe(t){if(!t||typeof t!="string")return"";let e=[/(\d{4})-(\d{2})-(\d{2})/,/(\d{2})\/(\d{2})\/(\d{4})/,/(\d{2})-(\d{2})-(\d{4})/];for(let n of e){let o=t.match(n);if(o){let r,i,s;return o[1].length===4?[r,i,s]=[o[1],o[2],o[3]]:[s,i,r]=[o[1],o[2],o[3]],`${r}${i}${s}`}}return""}function $(t){if(!t||typeof t.elements!="object")return{};let e=new FormData(t),n={},o=e.get("email")||e.get("user_email")||e.get("useremail");o&&(n.email=We(o));let r=e.get("phone")||e.get("telephone")||e.get("telefone")||e.get("celular");r&&(n.phone=Re(r));let i=e.get("first_name")||e.get("nome")||e.get("firstname"),s=e.get("last_name")||e.get("sobrenome")||e.get("lastname"),a=e.get("name")||e.get("fullname")||e.get("nome_completo");if(a){let d=a.split(" ");n.first_name=N(d[0]),n.last_name=N(d.slice(1).join(" "))}else i&&(n.first_name=N(i)),s&&(n.last_name=N(s));let u=e.get("city")||e.get("cidade");u&&(n.city=Ue(u));let m=e.get("state")||e.get("estado")||e.get("uf");m&&(n.state=Ye(m));let l=e.get("zip")||e.get("cep")||e.get("postalcode");l&&(n.zip=Ge(l));let g=e.get("dob")||e.get("date_of_birth")||e.get("nascimento");return g&&(n.dob=qe(g)),n}function Z(t){if(!t||typeof t!="object")return!1;let e=t.email&&t.email.includes("@"),n=t.phone&&t.phone.length>=10;return e||n}var I=typeof window!="undefined",w={endpoint:"/track",maxRetries:3,retryDelays:[1e3,3e3,6e3],useBeaconFallback:!0,cookieDuration:3600*24*365,cookieDomain:"",detectAdBlocker:!0,adBlockerBaitClass:"adsbox adbanner pub_300x250",minify:!1,noConsoleLogs:!1};function Je(){if(!I||!w.detectAdBlocker)return!1;let t=document.createElement("div");t.innerHTML=" ",t.className=w.adBlockerBaitClass,t.style.cssText="position: absolute; top: -1000px; left: -1000px;",document.body.appendChild(t);let e=getComputedStyle(t).display==="none";document.body.removeChild(t);try{let n=new Image;n.src="/pixel-test.png?t="+Date.now(),n.onload=()=>console.log("\u2705 Pixel n\xE3o bloqueado"),n.onerror=()=>console.warn("\u26A0\uFE0F Pixel pode estar bloqueado")}catch(n){console.warn("\u26A0\uFE0F Erro ao testar pixel:",n)}return e}async function Q(t,e=w.endpoint){if(!I)return{success:!1,error:"Not in browser"};let n=null;for(let o=0;o<w.maxRetries;o++)try{let r=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t),keepalive:!0,credentials:"same-origin",cache:"no-cache"});if(r.ok)return console.log(`\u2705 Envio bem-sucedido (tentativa ${o+1})`),await r.json();{let i=await r.text();throw new Error(`HTTP ${r.status}: ${i}`)}}catch(r){if(n=r,console.warn(`\u26A0\uFE0F Tentativa ${o+1} falhou:`,r.message),o<w.maxRetries-1){let i=w.retryDelays[o];console.log(`\u23F3 Aguardando ${i}ms antes de retry...`),await Ke(i)}}if(console.error("\u274C Todas as tentativas de envio falharam:",n),w.useBeaconFallback&&navigator.sendBeacon){if(console.log("\u{1F504} Tentando Beacon API como fallback..."),navigator.sendBeacon(e,JSON.stringify(t)))return console.log("\u2705 Beacon API bem-sucedido"),{success:!0,method:"beacon"};console.error("\u274C Beacon API tamb\xE9m falhou")}return{success:!1,error:n==null?void 0:n.message,attempts:w.maxRetries}}function Ke(t){return new Promise(e=>setTimeout(e,t))}function Xe(t,e,n=w.cookieDuration){if(!I)return;let r=window.location.hostname.split(".").slice(-2).join("."),i=[`${t}=${e}`,`max-age=${n}`,"path=/",`domain=.${r}`,"SameSite=Lax","Secure"].join("; ");document.cookie=i}function Ze(t){if(!I)return null;let n=`; ${document.cookie}`.split(`; ${t}=`);return n.length===2?n.pop().split(";").shift():null}function Qe(t=w.noConsoleLogs){if(!I||!t)return;let e=()=>{};console.log=e,console.warn=e,console.error=e}function ee(){if(!I)return;if(console.log("\u{1F6E1}\uFE0F Inicializando Anti-Blocking System..."),Je()&&(console.warn("\u26A0\uFE0F Ad-Blocker detectado - usando estrat\xE9gias de resili\xEAncia"),typeof cdpTrack!="undefined"&&cdpTrack.track&&cdpTrack.track("adblocker_detected",{user_agent:navigator.userAgent,timestamp:Date.now()})),!Ze("_cdp_uid")){let n=`${Date.now()}_${Math.random().toString(36).slice(2,11)}`;Xe("_cdp_uid",n)}w.noConsoleLogs&&Qe(!0),console.log("\u2705 Anti-Blocking System inicializado")}var et=typeof window!="undefined";function te(t={}){if(!et)return;let{whatsappNumber:e,propertyName:n="o im\xF3vel",propertyId:o=null,propertyLat:r=null,propertyLng:i=null,routeSelector:s='[data-route-intent], a[href*="maps/dir"], a[href*="maps?q="]',distanceBucket:a=null,distanceKm:u=null,metaSignalBucket:m=null,brokerName:l=null}=t;if(!e){console.warn("[RouteIntent] whatsappNumber \xE9 obrigat\xF3rio.");return}it(),document.addEventListener("click",g=>{let d=g.target.closest(s);d&&tt(d,{whatsappNumber:e,propertyName:n,propertyId:o,propertyLat:r,propertyLng:i,distanceBucket:a,distanceKm:u,metaSignalBucket:m,brokerName:l})},!0)}function tt(t,e){var s;(s=document.getElementById("cdp-ri-widget"))==null||s.remove();let n=ne(e.distanceKm),o=n?`<p class="cdp-ri-travel">\u{1F4CD} Voc\xEA est\xE1 a cerca de <strong>${n} min</strong> daqui</p>`:"",r=e.brokerName?`<p class="cdp-ri-broker">Ao chegar, pergunte pelo <strong>${e.brokerName}</strong> \u2014 ele vai estar te aguardando com tudo pronto \u{1F91D}</p>`:"",i=document.createElement("div");i.id="cdp-ri-widget",i.innerHTML=`
|
|
8
|
+
<div class="cdp-ri-inner">
|
|
9
|
+
${o}
|
|
10
|
+
<p class="cdp-ri-headline">Vi que voc\xEA quer visitar o local! Confirme sua vinda enviando a mensagem abaixo \u2014 nossa equipe j\xE1 fica de prontid\xE3o pra te receber \u{1F447}</p>
|
|
11
|
+
${r}
|
|
12
|
+
<button id="cdp-ri-btn" type="button">
|
|
13
|
+
${rt()} Confirmar minha visita
|
|
14
|
+
</button>
|
|
15
|
+
<button id="cdp-ri-dismiss" type="button" class="cdp-ri-dismiss">Agora n\xE3o</button>
|
|
16
|
+
</div>
|
|
17
|
+
`,t.insertAdjacentElement("afterend",i),setTimeout(()=>i.scrollIntoView({behavior:"smooth",block:"nearest"}),150),document.getElementById("cdp-ri-btn").addEventListener("click",()=>nt(i,e)),document.getElementById("cdp-ri-dismiss").addEventListener("click",()=>{var a,u;(u=(a=window.cdpTrack)==null?void 0:a.track)==null||u.call(a,"ViewContent",{content_name:"rota_dispensada",property_id:e.propertyId,funnel_stage:"route_dismiss",intent_score:"medium",distance_bucket:e.distanceBucket||void 0,meta_signal_bucket:e.metaSignalBucket||void 0}),i.remove()})}async function nt(t,e){var a,u;let n=document.getElementById("cdp-ri-btn");n&&(n.disabled=!0),(u=(a=window.cdpTrack)==null?void 0:a.track)==null||u.call(a,"Contact",{content_name:"aviso_chegada_whatsapp",property_id:e.propertyId,property_lat:e.propertyLat,property_lng:e.propertyLng,funnel_stage:"route_click",intent_score:"high",distance_bucket:e.distanceBucket||void 0,meta_signal_bucket:e.metaSignalBucket||void 0});let o=ne(e.distanceKm),r=o?`Estou a cerca de ${o} minutos da\xED.`:"",i=e.brokerName?`Vou procurar pelo ${e.brokerName} ao chegar.`:"",s=[`Oi! Estou interessado(a) em visitar o ${e.propertyName} e gostaria de confirmar minha visita.`,r,i||"Voc\xEAs conseguem me receber agora ou preciso marcar hor\xE1rio?"].filter(Boolean).join(" ");ot(t,e.whatsappNumber,s)}function ot(t,e,n){t.innerHTML=`
|
|
18
|
+
<div class="cdp-ri-inner cdp-ri-ok">
|
|
19
|
+
<span class="cdp-ri-check">\u2705</span>
|
|
20
|
+
<p><strong>Abrindo WhatsApp...</strong><br><span>A equipe j\xE1 foi avisada!</span></p>
|
|
21
|
+
</div>
|
|
22
|
+
`,setTimeout(()=>{window.open(`https://wa.me/${e}?text=${encodeURIComponent(n)}`,"_blank"),setTimeout(()=>t==null?void 0:t.remove(),3500)},600)}function ne(t){return!t||t<=0?null:Math.max(5,Math.round(t*60/25/5)*5)}function rt(){return`<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
|
|
23
|
+
<path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347z"/>
|
|
24
|
+
<path d="M12 0C5.373 0 0 5.373 0 12c0 2.122.554 4.118 1.528 5.852L0 24l6.335-1.513A11.933 11.933 0 0012 24c6.627 0 12-5.373 12-12S18.627 0 12 0zm0 21.818a9.818 9.818 0 01-5.002-1.368l-.359-.213-3.722.888.924-3.617-.234-.372A9.818 9.818 0 012.182 12C2.182 6.57 6.57 2.182 12 2.182S21.818 6.57 21.818 12 17.43 21.818 12 21.818z"/>
|
|
25
|
+
</svg>`}function it(){if(document.getElementById("cdp-ri-styles"))return;let t=document.createElement("style");t.id="cdp-ri-styles",t.textContent=`
|
|
26
|
+
#cdp-ri-widget {
|
|
27
|
+
margin-top: 12px;
|
|
28
|
+
padding: 16px 18px;
|
|
29
|
+
background: #f0fdf4;
|
|
30
|
+
border: 1.5px solid #22c55e;
|
|
31
|
+
border-radius: 12px;
|
|
32
|
+
font-family: Arial, sans-serif;
|
|
33
|
+
animation: cdp-ri-in .25s ease;
|
|
34
|
+
}
|
|
35
|
+
@keyframes cdp-ri-in {
|
|
36
|
+
from { opacity: 0; transform: translateY(-8px); }
|
|
37
|
+
to { opacity: 1; transform: translateY(0); }
|
|
38
|
+
}
|
|
39
|
+
.cdp-ri-inner { display: flex; flex-direction: column; gap: 10px; }
|
|
40
|
+
.cdp-ri-travel { margin: 0; font-size: 13px; color: #555; }
|
|
41
|
+
.cdp-ri-travel strong { color: #0f766e; }
|
|
42
|
+
.cdp-ri-headline { margin: 0; font-size: 14px; color: #15803d; font-weight: bold; line-height: 1.4; }
|
|
43
|
+
.cdp-ri-broker { margin: 0; font-size: 13px; color: #555; line-height: 1.4; }
|
|
44
|
+
.cdp-ri-broker strong { color: #0f766e; }
|
|
45
|
+
#cdp-ri-btn {
|
|
46
|
+
display: flex; align-items: center; justify-content: center; gap: 8px;
|
|
47
|
+
width: 100%; padding: 13px 16px;
|
|
48
|
+
background: #25D366; color: #fff;
|
|
49
|
+
border: none; border-radius: 10px;
|
|
50
|
+
font-size: 15px; font-weight: bold; cursor: pointer;
|
|
51
|
+
}
|
|
52
|
+
#cdp-ri-btn:hover { background: #1ebe5a; }
|
|
53
|
+
#cdp-ri-btn:disabled { background: #86efac; cursor: not-allowed; }
|
|
54
|
+
.cdp-ri-dismiss {
|
|
55
|
+
background: none; border: none;
|
|
56
|
+
color: #aaa; font-size: 12px;
|
|
57
|
+
cursor: pointer; padding: 2px 0; text-align: center;
|
|
58
|
+
}
|
|
59
|
+
.cdp-ri-dismiss:hover { color: #666; }
|
|
60
|
+
.cdp-ri-ok { align-items: center; text-align: center; gap: 8px; }
|
|
61
|
+
.cdp-ri-check { font-size: 28px; }
|
|
62
|
+
.cdp-ri-ok p { margin: 0; font-size: 14px; color: #15803d; line-height: 1.5; }
|
|
63
|
+
.cdp-ri-ok span { font-size: 13px; color: #555; }
|
|
64
|
+
`,document.head.appendChild(t)}var _=typeof window!="undefined";var ae="_cdp_consent",st={ad_storage:"denied",analytics_storage:"denied",ad_user_data:"denied",ad_personalization:"denied"};function ct(){if(!_)return null;try{let t=localStorage.getItem(ae);return t?JSON.parse(t):null}catch(t){return null}}function lt(){var o,r,i,s;if(!_||((o=h.consent)==null?void 0:o.defaultDenied)===!1)return;window.dataLayer=window.dataLayer||[];function t(){window.dataLayer.push(arguments)}let e=(i=(r=h.consent)==null?void 0:r.waitForUpdate)!=null?i:500;t("consent","default",{...st,wait_for_update:e}),((s=h.consent)==null?void 0:s.urlPassthrough)!==!1&&t("set","url_passthrough",!0);let n=ct();n&&(t("consent","update",n),h.debug&&console.log("\u2705 Consent Mode: consentimento anterior restaurado"))}function se(t={}){if(!_)return;window.dataLayer=window.dataLayer||[];function e(){window.dataLayer.push(arguments)}let n=t.analytics===!0?"granted":"denied",o=t.ads===!0?"granted":"denied",r={analytics_storage:n,ad_storage:o,ad_user_data:o,ad_personalization:o};e("consent","update",r);try{localStorage.setItem(ae,JSON.stringify(r))}catch(i){}console.log("\u2705 Consent Mode atualizado:",r)}var S=_?new URLSearchParams(window.location.search):new URLSearchParams,dt=S.get("fbclid")||"",ut=S.get("gclid")||"",mt=S.get("wbraid")||"",gt=S.get("gbraid")||"",pt=S.get("ttclid")||"",j={utm_source:S.get("utm_source")||"",utm_medium:S.get("utm_medium")||"",utm_campaign:S.get("utm_campaign")||"",utm_content:S.get("utm_content")||"",utm_term:S.get("utm_term")||""},ft=()=>{var n;if(!_)return"";let t="_cdp_uid",e=(n=document.cookie.match(new RegExp(`${t}=([^;]+)`)))==null?void 0:n[1];return e||(e=`${Date.now()}_${Math.random().toString(36).slice(2,11)}`,document.cookie=`${t}=${e}; max-age=${3600*24*365}; path=/; SameSite=Lax`),e},R=_?ft():"",ht=()=>{if(!_)return"";let t="cdp_session",e=sessionStorage.getItem(t);return e||(e=`${Date.now()}_${Math.random().toString(36).slice(2,11)}`,sessionStorage.setItem(t,e)),e},_t=_?ht():"",A=()=>({...j}),B=()=>R,U=()=>_t,ce=()=>`${Date.now()}_${Math.random().toString(36).slice(2,11)}`,kt=()=>{var t,e,n;return{fbp:((t=document.cookie.match(/_fbp=([^;]+)/))==null?void 0:t[1])||void 0,fbc:((e=document.cookie.match(/_fbc=([^;]+)/))==null?void 0:e[1])||void 0,fbclid:dt||void 0,gclid:ut||void 0,gbraid:gt||void 0,wbraid:mt||void 0,ttclid:pt||void 0,ttp:((n=document.cookie.match(/_ttp=([^;]+)/))==null?void 0:n[1])||void 0,rclid:S.get("rclid")||void 0}},le=(t={})=>{if(!_)return;let{platforms:e=["hotmart","kiwify","eduzz","monetizze","cartpanda","ticto"],domains:n=[]}=t,o=A(),r=B(),i={hotmart:["hotmart.com","pay.hotmart.com","payment.hotmart.com"],kiwify:["kiwify.com.br","checkout.kiwify.com.br"],eduzz:["eduzz.com","sun.eduzz.com"],monetizze:["monetizze.com.br"],cartpanda:["cartpanda.com","pay.cartpanda.com"],ticto:["ticto.app","pay.ticto.app","checkout.ticto.app"]},s=()=>[o.utm_source,o.utm_medium,o.utm_campaign,o.utm_content,o.utm_term].map(m=>m||"direto").join("|"),a=m=>{let l={...n},g=m.toLowerCase(),d=k=>k.some(y=>g.includes(y));if(e.includes("hotmart")&&d(i.hotmart))r&&(l.xcod=r),o.utm_source&&(l.sck=s());else if(e.includes("kiwify")&&d(i.kiwify))o.utm_source&&(l.src=o.utm_source),o.utm_medium&&(l.utm_medium=o.utm_medium),o.utm_campaign&&(l.utm_campaign=o.utm_campaign);else if(e.includes("eduzz")&&d(i.eduzz))o.utm_source&&(l.src=o.utm_source);else if(e.includes("monetizze")&&d(i.monetizze))o.utm_source&&(l.src=o.utm_source);else if(e.includes("cartpanda")&&d(i.cartpanda))Object.entries(o).forEach(([k,y])=>{y&&(l[k]=y)});else if(e.includes("ticto")&&d(i.ticto))Object.entries(o).forEach(([k,y])=>{y&&(l[k]=y)}),r&&(l.user_id=r);else{let k=Object.values(i).flat().concat(n);if(!d(k))return null;Object.entries(o).forEach(([y,b])=>{b&&(l[y]=b)}),r&&(l.user_id=r)}return Object.keys(l).length?l:null},u=m=>{if(!m.href||m.href.startsWith("javascript"))return;let l=a(m);if(l)try{let g=new URL(m.href);Object.entries(l).forEach(([d,k])=>g.searchParams.set(d,k)),m.href=g.toString()}catch(g){}};document.querySelectorAll("a[href]").forEach(u),new MutationObserver(m=>{m.forEach(l=>l.addedNodes.forEach(g=>{var d;g.nodeType===1&&(g.tagName==="A"&&u(g),(d=g.querySelectorAll)==null||d.call(g,"a[href]").forEach(u))}))}).observe(document.body,{childList:!0,subtree:!0}),console.log("\u2705 PassCheckoutParams inicializado")},W="_cdp_aff";function vt(){if(_)try{let t=Object.values(j).some(n=>!!n),e=Y();(t||!e)&&localStorage.setItem(W,JSON.stringify({uid:R,utms:j,ts:Date.now()}))}catch(t){}}function Y(){if(!_)return null;try{let t=localStorage.getItem(W);if(!t)return null;let e=JSON.parse(t);return Date.now()-e.ts>720*60*60*1e3?(localStorage.removeItem(W),null):e}catch(t){return null}}function de(){let t=A();if(Object.values(t).some(n=>!!n))return t;let e=Y();return e!=null&&e.utms&&Object.values(e.utms).some(n=>!!n)?(h.debug&&console.log("\u2139\uFE0F UTMs restaurados do localStorage (affiliate fallback)"),e.utms):t}function ue(){var t;return R||((t=Y())==null?void 0:t.uid)||""}async function D(t,e={},n={}){if(!_)return console.warn("\u26A0\uFE0F cdpTrack.track() deve ser chamado no browser"),{success:!1,error:"Not in browser"};let o=ce(),r=A(),i=kt(),s=B(),a=U(),u=Date.now(),m=X(),{totalScore:l,timeLevel:g,scrollScore:d,clickScore:k,videoScore:y,hoverScore:b,intentionLevel:_e}=m,ke={event_id:o,event_name:t,user_id:s,session_id:a,utms:r,click_ids:i,timestamp:u,page_url:window.location.href,referrer:document.referrer,user_agent:navigator.userAgent,behavioral_data:{...e,engagement_score:l,time_level:g,scroll_score:d,click_score:k,video_score:y,hover_score:b,intention_level:_e},...n};try{let C=await Q(ke,"/track");if(C.success)return console.log(`\u2705 Evento ${t} enviado com sucesso:`,o,C),F("timeOnPage",Math.round((Date.now()-u)/1e3)),F("totalScore",l),{success:!0,event_id:o,result:C};throw new Error(C.error||"Envio falhou ap\xF3s todas as tentativas")}catch(C){return console.error(`\u274C Erro ao enviar evento ${t}:`,C),{success:!1,error:C.message,event_id:o,attempts:w.maxRetries}}}async function G(t,e=null){let n={...t};if(e){let o=$(e);n={...n,...o}}return D("Lead",n)}async function me(t,e=null){let n={...t};if(e){let o=$(e);n={...n,...o}}return D("Purchase",n)}function ge(){_&&document.addEventListener("submit",async t=>{let e=t.target,n=e.querySelector('[name*="email"]'),o=e.querySelector('[name*="phone"], [name*="telefone"], [name*="celular"]');if(n||o){t.preventDefault();let r=$(e);Z(r)&&(await G(r,e),console.log("\u2705 Lead capturado automaticamente com Advanced Matching:",r)),setTimeout(()=>e.submit(),100)}},!0)}async function pe(t){return D("ViewContent",t)}async function fe(t){return D("AddToCart",t)}async function he(){var t,e;if(_){if(h.debug&&console.log("\u{1F680} Inicializando cdpTrack SDK..."),lt(),ee(),vt(),K(),h.autoCaptureForms!==!1&&ge(),window.cdpTrack={track:D,trackLead:G,trackPurchase:me,trackViewContent:pe,trackAddToCart:fe,getUserId:B,getUserIdWithFallback:ue,getSessionId:U,getUTMs:A,getUTMsWithFallback:de,updateConsent:se},h.initBehaviorEngine!==!1)try{let o=(await Promise.resolve().then(()=>(ie(),re))).default;o&&typeof o.init=="function"&&(o.init(),h.debug&&console.log("\u2705 Behavior Engine inicializado"))}catch(n){h.debug&&console.info("\u2139\uFE0F Behavior Engine n\xE3o dispon\xEDvel:",n.message)}h.passCheckoutParams!==!1&&((t=h.platforms)==null?void 0:t.length)>0&&le({platforms:h.platforms}),(e=h.routeIntent)!=null&&e.whatsappNumber&&te(h.routeIntent),h.debug&&console.log("\u2705 cdpTrack SDK inicializado (Quantum Tier)")}}_&&window.addEventListener("DOMContentLoaded",he);return be(yt);})();
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<!-- CDP Edge SDK v2.5.1 — instalar antes do </body> -->
|
|
2
|
+
<script src="/cdpTrack.min.js"></script>
|
|
3
|
+
<script>
|
|
4
|
+
// Inicializar após carregar
|
|
5
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
6
|
+
if (window.cdpTrack && window.cdpTrack.init) {
|
|
7
|
+
window.cdpTrack.init();
|
|
8
|
+
}
|
|
9
|
+
});
|
|
10
|
+
</script>
|
|
@@ -552,16 +552,6 @@ export function setupAutoFormCapture() {
|
|
|
552
552
|
}, true); // Capture para formulários dinâmicos
|
|
553
553
|
}
|
|
554
554
|
|
|
555
|
-
/**
|
|
556
|
-
* trackPurchase() — Captura de compra
|
|
557
|
-
*
|
|
558
|
-
* @param {object} orderData - Dados da compra (order_id, value, currency, etc.)
|
|
559
|
-
* @returns {Promise} - Promise com resultado
|
|
560
|
-
*/
|
|
561
|
-
export async function trackPurchase(orderData) {
|
|
562
|
-
return track('Purchase', orderData);
|
|
563
|
-
}
|
|
564
|
-
|
|
565
555
|
/**
|
|
566
556
|
* trackViewContent() — Captura de visualização de conteúdo
|
|
567
557
|
*
|
|
@@ -21,8 +21,8 @@ const ENGAGEMENT_CONFIG = {
|
|
|
21
21
|
clickWeights: {
|
|
22
22
|
'generico': 1.0, // clique sem categoria
|
|
23
23
|
'cta': 2.5, // clique em CTA
|
|
24
|
-
'button': 2.0
|
|
25
|
-
'link': 1.5
|
|
24
|
+
'button': 2.0, // clique em botão
|
|
25
|
+
'link': 1.5, // clique em link
|
|
26
26
|
'input': 0.5, // clique em input
|
|
27
27
|
},
|
|
28
28
|
videoWeights: {
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
const CONFIG = {
|
|
11
11
|
// ── Endpoint do Cloudflare Worker ────────────────────────────────────────────
|
|
12
12
|
// Same-domain: evita ad-blockers e CORS.
|
|
13
|
-
// Em produção: seu-dominio.com.br/
|
|
14
|
-
// Em dev: use o URL do Worker diretamente
|
|
15
|
-
endpoint: '/
|
|
13
|
+
// Em produção: seu-dominio.com.br/track (Worker roteado via Custom Domain)
|
|
14
|
+
// Em dev: use o URL do Worker diretamente (ex: https://worker.seu-dominio.workers.dev/track)
|
|
15
|
+
endpoint: '/track',
|
|
16
16
|
|
|
17
17
|
// ── Plataformas de checkout habilitadas ──────────────────────────────────────
|
|
18
18
|
// Controla quais plataformas recebem passCheckoutParams() automaticamente.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cdp-edge",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.1",
|
|
4
4
|
"description": "CDP Edge - Quantum Tracking - Sistema multi-agente para tracking digital Cloudflare Native (Workers + D1)",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"contracts",
|
|
16
16
|
"extracted-skill",
|
|
17
17
|
"server-edge-tracker",
|
|
18
|
+
"scripts/build-sdk.js",
|
|
18
19
|
"docs",
|
|
19
20
|
"README.md"
|
|
20
21
|
],
|
|
@@ -35,6 +36,8 @@
|
|
|
35
36
|
"agents:sync": "node scripts/sync-agents.js",
|
|
36
37
|
"agents:sync:list": "node scripts/sync-agents.js --list",
|
|
37
38
|
"agents:sync:all": "node scripts/sync-agents.js --apply-all",
|
|
39
|
+
"sdk:build": "node scripts/build-sdk.js",
|
|
40
|
+
"sdk:build:debug": "node scripts/build-sdk.js --debug",
|
|
38
41
|
"typecheck": "tsc --noEmit"
|
|
39
42
|
},
|
|
40
43
|
"keywords": [
|
|
@@ -79,6 +82,7 @@
|
|
|
79
82
|
"@semantic-release/npm": "^13.1.5",
|
|
80
83
|
"@semantic-release/release-notes-generator": "^14.1.0",
|
|
81
84
|
"@types/node": "^20.19.39",
|
|
85
|
+
"esbuild": "^0.28.0",
|
|
82
86
|
"semantic-release": "^25.0.3",
|
|
83
87
|
"typescript": "^6.0.2"
|
|
84
88
|
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CDP Edge — SDK Build Script
|
|
3
|
+
*
|
|
4
|
+
* Gera cdpTrack.min.js: bundle único pronto para <script src=""> em qualquer site.
|
|
5
|
+
* Entrada: extracted-skill/tracking-events-generator/cdpTrack.js (ES Module)
|
|
6
|
+
* Saída: dist/sdk/cdpTrack.min.js — minificado (produção)
|
|
7
|
+
* dist/sdk/cdpTrack.js — legível (debug)
|
|
8
|
+
*
|
|
9
|
+
* Uso:
|
|
10
|
+
* node scripts/build-sdk.js
|
|
11
|
+
* node scripts/build-sdk.js --debug (só versão legível)
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { build } from 'esbuild';
|
|
15
|
+
import { readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
16
|
+
import { resolve, dirname } from 'path';
|
|
17
|
+
import { fileURLToPath } from 'url';
|
|
18
|
+
|
|
19
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
20
|
+
const ROOT = resolve(__dirname, '..');
|
|
21
|
+
const SDK_DIR = resolve(ROOT, 'extracted-skill/tracking-events-generator');
|
|
22
|
+
const OUT_DIR = resolve(ROOT, 'dist/sdk');
|
|
23
|
+
|
|
24
|
+
const debugOnly = process.argv.includes('--debug');
|
|
25
|
+
|
|
26
|
+
// Garante que o diretório de saída existe
|
|
27
|
+
mkdirSync(OUT_DIR, { recursive: true });
|
|
28
|
+
|
|
29
|
+
// ── Banner do bundle ──────────────────────────────────────────────────────────
|
|
30
|
+
const pkg = JSON.parse(readFileSync(resolve(ROOT, 'package.json'), 'utf-8'));
|
|
31
|
+
const banner = `/*!
|
|
32
|
+
* CDP Edge SDK v${pkg.version}
|
|
33
|
+
* (c) ${new Date().getFullYear()} CDP Edge — Quantum Tracking
|
|
34
|
+
* Gerado em: ${new Date().toISOString()}
|
|
35
|
+
* Endpoint padrão: /track (mesmo domínio — anti-adblock)
|
|
36
|
+
*/`;
|
|
37
|
+
|
|
38
|
+
// ── Configuração base do esbuild ──────────────────────────────────────────────
|
|
39
|
+
const baseConfig = {
|
|
40
|
+
entryPoints: [resolve(SDK_DIR, 'cdpTrack.js')],
|
|
41
|
+
bundle: true,
|
|
42
|
+
format: 'iife', // <script> tag — expõe window.cdpTrack
|
|
43
|
+
globalName: 'cdpTrack', // window.cdpTrack após carregar
|
|
44
|
+
platform: 'browser',
|
|
45
|
+
target: ['es2018'], // suporta Safari 12+, Chrome 69+, Firefox 62+
|
|
46
|
+
banner: { js: banner },
|
|
47
|
+
define: {
|
|
48
|
+
'process.env.NODE_ENV': '"production"',
|
|
49
|
+
},
|
|
50
|
+
// Resolve módulos locais pelo diretório do SDK
|
|
51
|
+
absWorkingDir: SDK_DIR,
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
async function buildSDK() {
|
|
55
|
+
console.log('🏗️ Buildando CDP Edge SDK...\n');
|
|
56
|
+
|
|
57
|
+
// ── Versão debug (legível) ────────────────────────────────────────────────
|
|
58
|
+
console.log('📦 Gerando cdpTrack.js (debug)...');
|
|
59
|
+
await build({
|
|
60
|
+
...baseConfig,
|
|
61
|
+
outfile: resolve(OUT_DIR, 'cdpTrack.js'),
|
|
62
|
+
minify: false,
|
|
63
|
+
sourcemap: false,
|
|
64
|
+
});
|
|
65
|
+
const debugSize = (readFileSync(resolve(OUT_DIR, 'cdpTrack.js')).length / 1024).toFixed(1);
|
|
66
|
+
console.log(` ✓ dist/sdk/cdpTrack.js — ${debugSize} kB`);
|
|
67
|
+
|
|
68
|
+
if (!debugOnly) {
|
|
69
|
+
// ── Versão produção (minificada) ────────────────────────────────────────
|
|
70
|
+
console.log('📦 Gerando cdpTrack.min.js (produção)...');
|
|
71
|
+
await build({
|
|
72
|
+
...baseConfig,
|
|
73
|
+
outfile: resolve(OUT_DIR, 'cdpTrack.min.js'),
|
|
74
|
+
minify: true,
|
|
75
|
+
sourcemap: false,
|
|
76
|
+
});
|
|
77
|
+
const minSize = (readFileSync(resolve(OUT_DIR, 'cdpTrack.min.js')).length / 1024).toFixed(1);
|
|
78
|
+
console.log(` ✓ dist/sdk/cdpTrack.min.js — ${minSize} kB`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ── Gera snippet de instalação ────────────────────────────────────────────
|
|
82
|
+
const snippet = `<!-- CDP Edge SDK v${pkg.version} — instalar antes do </body> -->
|
|
83
|
+
<script src="/cdpTrack.min.js"></script>
|
|
84
|
+
<script>
|
|
85
|
+
// Inicializar após carregar
|
|
86
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
87
|
+
if (window.cdpTrack && window.cdpTrack.init) {
|
|
88
|
+
window.cdpTrack.init();
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
</script>`;
|
|
92
|
+
|
|
93
|
+
writeFileSync(resolve(OUT_DIR, 'install-snippet.html'), snippet, 'utf-8');
|
|
94
|
+
console.log(` ✓ dist/sdk/install-snippet.html — snippet de instalação\n`);
|
|
95
|
+
|
|
96
|
+
console.log('✅ SDK build concluído!');
|
|
97
|
+
console.log('\n📋 Próximos passos para o cliente:');
|
|
98
|
+
console.log(' 1. Copiar dist/sdk/cdpTrack.min.js para a raiz do site');
|
|
99
|
+
console.log(' 2. Adicionar snippet de dist/sdk/install-snippet.html antes de </body>');
|
|
100
|
+
console.log(' 3. O Worker deve estar no mesmo domínio (Custom Domain Cloudflare → /track)\n');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
buildSDK().catch(err => {
|
|
104
|
+
console.error('❌ Build falhou:', err.message);
|
|
105
|
+
process.exit(1);
|
|
106
|
+
});
|
|
@@ -255,6 +255,99 @@ export default {
|
|
|
255
255
|
}, null, 2), { headers });
|
|
256
256
|
}
|
|
257
257
|
|
|
258
|
+
// ── GET /validate-install ─────────────────────────────────────────────────
|
|
259
|
+
// Endpoint de diagnóstico pós-deploy. Chamado por `cdp-edge validate <url>`.
|
|
260
|
+
// Testa D1 write/read, KV, AI e retorna relatório estruturado.
|
|
261
|
+
// Protegido: só aceita requisições com header CDP-Validate: 1
|
|
262
|
+
if (request.method === 'GET' && url.pathname === '/validate-install') {
|
|
263
|
+
if (request.headers.get('CDP-Validate') !== '1') {
|
|
264
|
+
return new Response(JSON.stringify({ error: 'Unauthorized' }), { status: 401, headers });
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const report: Record<string, { ok: boolean; detail: string }> = {};
|
|
268
|
+
|
|
269
|
+
// 1. D1 write + read
|
|
270
|
+
try {
|
|
271
|
+
const testId = `__cdp_validate_${Date.now()}__`;
|
|
272
|
+
await env.DB?.prepare(
|
|
273
|
+
`INSERT OR REPLACE INTO events (event_id, event_name, user_id, created_at)
|
|
274
|
+
VALUES (?, '__validate__', '__validate__', datetime('now'))`
|
|
275
|
+
).bind(testId).run();
|
|
276
|
+
const row = await env.DB?.prepare(
|
|
277
|
+
`SELECT event_id FROM events WHERE event_id = ?`
|
|
278
|
+
).bind(testId).first();
|
|
279
|
+
await env.DB?.prepare(`DELETE FROM events WHERE event_id = ?`).bind(testId).run();
|
|
280
|
+
report.d1 = { ok: !!row, detail: row ? 'write+read+delete OK' : 'row not found after insert' };
|
|
281
|
+
} catch (err: any) {
|
|
282
|
+
report.d1 = { ok: false, detail: err?.message || String(err) };
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// 2. KV read/write
|
|
286
|
+
try {
|
|
287
|
+
await env.GEO_CACHE?.put('__cdp_validate__', '1', { expirationTtl: 60 });
|
|
288
|
+
const val = await env.GEO_CACHE?.get('__cdp_validate__');
|
|
289
|
+
report.kv = { ok: val === '1', detail: val === '1' ? 'write+read OK' : 'value mismatch' };
|
|
290
|
+
} catch (err: any) {
|
|
291
|
+
report.kv = { ok: false, detail: err?.message || String(err) };
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// 3. Workers AI
|
|
295
|
+
try {
|
|
296
|
+
await env.AI?.run('@cf/ibm-granite/granite-4.0-h-micro', {
|
|
297
|
+
messages: [{ role: 'user', content: 'ping' }],
|
|
298
|
+
max_tokens: 1,
|
|
299
|
+
});
|
|
300
|
+
report.ai = { ok: true, detail: 'Granite 4.0 Micro respondeu' };
|
|
301
|
+
} catch (err: any) {
|
|
302
|
+
report.ai = { ok: false, detail: err?.message || String(err) };
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// 4. Secrets críticos
|
|
306
|
+
const missing: string[] = [];
|
|
307
|
+
if (!env.META_PIXEL_ID) missing.push('META_PIXEL_ID');
|
|
308
|
+
if (!env.META_ACCESS_TOKEN) missing.push('META_ACCESS_TOKEN');
|
|
309
|
+
if (!env.SITE_DOMAIN) missing.push('SITE_DOMAIN');
|
|
310
|
+
report.secrets = {
|
|
311
|
+
ok: missing.length === 0,
|
|
312
|
+
detail: missing.length === 0 ? 'todos os secrets críticos configurados' : `MISSING: ${missing.join(', ')}`,
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
// 5. /track endpoint (auto-teste)
|
|
316
|
+
const trackTest = { ok: false, detail: '' };
|
|
317
|
+
try {
|
|
318
|
+
const testPayload = {
|
|
319
|
+
eventName: 'PageView',
|
|
320
|
+
userId: '__cdp_validate__',
|
|
321
|
+
pageUrl: `https://${env.SITE_DOMAIN || 'validate.test'}/`,
|
|
322
|
+
userAgent: request.headers.get('User-Agent') || '',
|
|
323
|
+
ip: request.headers.get('CF-Connecting-IP') || '',
|
|
324
|
+
_validate: true,
|
|
325
|
+
};
|
|
326
|
+
const internalReq = new Request(`https://${env.SITE_DOMAIN || 'localhost'}/track`, {
|
|
327
|
+
method: 'POST',
|
|
328
|
+
headers: { 'Content-Type': 'application/json', 'CDP-Validate': '1' },
|
|
329
|
+
body: JSON.stringify(testPayload),
|
|
330
|
+
});
|
|
331
|
+
// Não chama fetch externo — apenas verifica que o payload seria aceito
|
|
332
|
+
const hasRequired = testPayload.eventName && testPayload.userId;
|
|
333
|
+
trackTest.ok = !!hasRequired;
|
|
334
|
+
trackTest.detail = hasRequired ? 'payload de teste válido (eventName + userId presentes)' : 'payload inválido';
|
|
335
|
+
} catch (err: any) {
|
|
336
|
+
trackTest.detail = err?.message || String(err);
|
|
337
|
+
}
|
|
338
|
+
report.track_endpoint = trackTest;
|
|
339
|
+
|
|
340
|
+
const allOk = Object.values(report).every(r => r.ok);
|
|
341
|
+
return new Response(JSON.stringify({
|
|
342
|
+
status: allOk ? 'ok' : 'degraded',
|
|
343
|
+
timestamp: new Date().toISOString(),
|
|
344
|
+
checks: report,
|
|
345
|
+
}, null, 2), {
|
|
346
|
+
status: allOk ? 200 : 207,
|
|
347
|
+
headers,
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
|
|
258
351
|
// ── POST /track ───────────────────────────────────────────────────────────
|
|
259
352
|
if (request.method === 'POST' && url.pathname === '/track') {
|
|
260
353
|
// Reject oversized payloads before reading body (64 KB limit)
|