cdp-edge 2.3.9 → 2.5.2
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 +54 -4
- package/bin/cdp-edge.js +3 -2
- package/contracts/agent-versions.json +383 -83
- 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/agents/ab-ltv-agent.md +1 -1
- package/extracted-skill/tracking-events-generator/agents/ab-testing-agent.md +1 -1
- package/extracted-skill/tracking-events-generator/agents/attribution-agent.md +18 -18
- package/extracted-skill/tracking-events-generator/agents/bidding-agent.md +1 -1
- package/extracted-skill/tracking-events-generator/agents/bing-agent.md +1 -1
- package/extracted-skill/tracking-events-generator/agents/code-guardian-agent.md +1 -1
- package/extracted-skill/tracking-events-generator/agents/compliance-agent.md +5 -5
- package/extracted-skill/tracking-events-generator/agents/crm-integration-agent.md +10 -10
- package/extracted-skill/tracking-events-generator/agents/dashboard-agent.md +3 -3
- package/extracted-skill/tracking-events-generator/agents/database-agent.md +17 -25
- package/extracted-skill/tracking-events-generator/agents/debug-agent.md +9 -9
- package/extracted-skill/tracking-events-generator/agents/devops-agent.md +18 -1
- package/extracted-skill/tracking-events-generator/agents/domain-setup-agent.md +5 -5
- package/extracted-skill/tracking-events-generator/agents/email-agent.md +3 -3
- package/extracted-skill/tracking-events-generator/agents/fingerprint-agent.md +4 -4
- package/extracted-skill/tracking-events-generator/agents/fraud-detection-agent.md +2 -0
- package/extracted-skill/tracking-events-generator/agents/google-agent.md +2 -2
- package/extracted-skill/tracking-events-generator/agents/intelligence-agent.md +23 -29
- package/extracted-skill/tracking-events-generator/agents/linkedin-agent.md +3 -3
- package/extracted-skill/tracking-events-generator/agents/localization-agent.md +1 -1
- package/extracted-skill/tracking-events-generator/agents/ltv-predictor-agent.md +1 -1
- package/extracted-skill/tracking-events-generator/agents/master-feedback-loop.md +16 -16
- package/extracted-skill/tracking-events-generator/agents/master-orchestrator.md +13 -13
- package/extracted-skill/tracking-events-generator/agents/memory-agent.md +14 -14
- package/extracted-skill/tracking-events-generator/agents/meta-agent.md +2 -2
- package/extracted-skill/tracking-events-generator/agents/ml-clustering-agent.md +9 -9
- package/extracted-skill/tracking-events-generator/agents/page-analyzer.md +1 -0
- package/extracted-skill/tracking-events-generator/agents/performance-agent.md +12 -12
- package/extracted-skill/tracking-events-generator/agents/performance-optimization-agent.md +7 -7
- package/extracted-skill/tracking-events-generator/agents/pinterest-agent.md +6 -6
- package/extracted-skill/tracking-events-generator/agents/premium-tracking-intelligence-agent.md +3 -3
- package/extracted-skill/tracking-events-generator/agents/r2-setup-agent.md +8 -8
- package/extracted-skill/tracking-events-generator/agents/reddit-agent.md +7 -7
- package/extracted-skill/tracking-events-generator/agents/security-enterprise-agent.md +21 -21
- package/extracted-skill/tracking-events-generator/agents/server-tracking.md +15 -15
- package/extracted-skill/tracking-events-generator/agents/spotify-agent.md +6 -6
- package/extracted-skill/tracking-events-generator/agents/tiktok-agent.md +3 -3
- package/extracted-skill/tracking-events-generator/agents/tracking-plan-agent.md +5 -5
- package/extracted-skill/tracking-events-generator/agents/validator-agent.md +9 -9
- package/extracted-skill/tracking-events-generator/agents/webhook-agent.md +4 -4
- package/extracted-skill/tracking-events-generator/agents/whatsapp-agent.md +1 -1
- package/extracted-skill/tracking-events-generator/agents/whatsapp-ctwa-setup-agent.md +3 -3
- package/extracted-skill/tracking-events-generator/agents/youtube-agent.md +9 -9
- 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
- package/server-edge-tracker/schema-utm.sql +5 -3
- package/server-edge-tracker/wrangler.toml +1 -1
- package/extracted-skill/tracking-events-generator/agents/intelligence-scheduling.md +0 -10
|
@@ -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>
|
|
@@ -39,7 +39,7 @@ POST /api/ltv/ab-test/winner → aplica vencedor ao LTV padrão
|
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
**Upstream (de onde recebe dados):**
|
|
42
|
-
- `
|
|
42
|
+
- `index.ts → predictLtv()` — ponto de interceptação do teste
|
|
43
43
|
- `webhook events` — fonte verdade do revenue real para scoring
|
|
44
44
|
|
|
45
45
|
**Downstream (quem consome outputs):**
|
|
@@ -44,7 +44,7 @@ Browser (Cliente) Worker (Server-Side) APIs (Meta/Google/TikT
|
|
|
44
44
|
|
|
45
45
|
**Uso:** Campanhas de última milha, conversão rápida.
|
|
46
46
|
|
|
47
|
-
```
|
|
47
|
+
```typescript
|
|
48
48
|
function lastClickAttribution(touchpoints) {
|
|
49
49
|
if (!touchpoints || touchpoints.length === 0) return [];
|
|
50
50
|
|
|
@@ -69,7 +69,7 @@ function lastClickAttribution(touchpoints) {
|
|
|
69
69
|
|
|
70
70
|
**Uso:** Brand awareness, campanhas de descoberta.
|
|
71
71
|
|
|
72
|
-
```
|
|
72
|
+
```typescript
|
|
73
73
|
function firstClickAttribution(touchpoints) {
|
|
74
74
|
if (!touchpoints || touchpoints.length === 0) return [];
|
|
75
75
|
|
|
@@ -94,7 +94,7 @@ function firstClickAttribution(touchpoints) {
|
|
|
94
94
|
|
|
95
95
|
**Uso:** Jornadas longas, múltiplos touchpoints importantes.
|
|
96
96
|
|
|
97
|
-
```
|
|
97
|
+
```typescript
|
|
98
98
|
function linearAttribution(touchpoints) {
|
|
99
99
|
if (!touchpoints || touchpoints.length === 0) return [];
|
|
100
100
|
|
|
@@ -122,7 +122,7 @@ function linearAttribution(touchpoints) {
|
|
|
122
122
|
|
|
123
123
|
**Fórmula:** `Credit = 0.9^dias_desde_touchpoint`
|
|
124
124
|
|
|
125
|
-
```
|
|
125
|
+
```typescript
|
|
126
126
|
function timeDecayAttribution(touchpoints, decayFactor = 0.9) {
|
|
127
127
|
if (!touchpoints || touchpoints.length === 0) return [];
|
|
128
128
|
|
|
@@ -165,7 +165,7 @@ function timeDecayAttribution(touchpoints, decayFactor = 0.9) {
|
|
|
165
165
|
|
|
166
166
|
**Uso:** Funis com pesquisa (awareness) + conversão direta.
|
|
167
167
|
|
|
168
|
-
```
|
|
168
|
+
```typescript
|
|
169
169
|
function uShapeAttribution(touchpoints) {
|
|
170
170
|
if (!touchpoints || touchpoints.length === 0) return [];
|
|
171
171
|
|
|
@@ -207,7 +207,7 @@ function uShapeAttribution(touchpoints) {
|
|
|
207
207
|
|
|
208
208
|
**Uso:** Funis muito longos, jornada complexa.
|
|
209
209
|
|
|
210
|
-
```
|
|
210
|
+
```typescript
|
|
211
211
|
function wShapeAttribution(touchpoints) {
|
|
212
212
|
if (!touchpoints || touchpoints.length === 0) return [];
|
|
213
213
|
|
|
@@ -262,7 +262,7 @@ function wShapeAttribution(touchpoints) {
|
|
|
262
262
|
|
|
263
263
|
**Fórmula:** `Credit = BaseScore * CanalWeight * PositionWeight * ConversionRateWeight`
|
|
264
264
|
|
|
265
|
-
```
|
|
265
|
+
```typescript
|
|
266
266
|
// Modelo Data-Driven simplificado
|
|
267
267
|
async function dataDrivenAttribution(touchpoints, userJourneyHistory, env) {
|
|
268
268
|
if (!touchpoints || touchpoints.length === 0) return [];
|
|
@@ -456,7 +456,7 @@ CREATE INDEX IF NOT EXISTS idx_channel_model ON channel_performance(attribution_
|
|
|
456
456
|
|
|
457
457
|
### 2.1 Captura de Jornada Completa
|
|
458
458
|
|
|
459
|
-
```
|
|
459
|
+
```typescript
|
|
460
460
|
// Capturar touchpoint da jornada
|
|
461
461
|
export async function captureTouchpoint(eventData, request, env) {
|
|
462
462
|
const {
|
|
@@ -536,7 +536,7 @@ async function scheduleAttributionCalculation(email, conversionId, eventName, en
|
|
|
536
536
|
|
|
537
537
|
### 2.2 Cálculo de Atribuição Multi-Touch
|
|
538
538
|
|
|
539
|
-
```
|
|
539
|
+
```typescript
|
|
540
540
|
// Calcular atribuição multi-touch
|
|
541
541
|
export async function calculateMultiTouchAttribution(conversionData, env) {
|
|
542
542
|
const {
|
|
@@ -683,7 +683,7 @@ async function updateChannelPerformance(attributionModels, value, currency, env)
|
|
|
683
683
|
|
|
684
684
|
### 2.3 Enviar Atribuição para Plataformas
|
|
685
685
|
|
|
686
|
-
```
|
|
686
|
+
```typescript
|
|
687
687
|
// Enviar Purchase com atribuição calculada
|
|
688
688
|
export async function sendPurchaseWithAttribution(conversionData, env, attributionModel = 'U_SHAPE') {
|
|
689
689
|
const {
|
|
@@ -914,7 +914,7 @@ async function sendGA4PurchaseWithAttribution(purchaseData, channelValues) {
|
|
|
914
914
|
|
|
915
915
|
### 3.1 Configuração via Arquivo
|
|
916
916
|
|
|
917
|
-
```
|
|
917
|
+
```typescript
|
|
918
918
|
// attribution.config.js
|
|
919
919
|
export const ATTRIBUTION_CONFIG = {
|
|
920
920
|
// Modelo padrão para cálculo de atribuição
|
|
@@ -1024,7 +1024,7 @@ export default ATTRIBUTION_CONFIG;
|
|
|
1024
1024
|
|
|
1025
1025
|
### 4.1 Endpoint de Atribuição
|
|
1026
1026
|
|
|
1027
|
-
```
|
|
1027
|
+
```typescript
|
|
1028
1028
|
// Endpoint para consultar atribuição de conversão
|
|
1029
1029
|
export async function getAttributionForConversion(request, env) {
|
|
1030
1030
|
const url = new URL(request.url);
|
|
@@ -1167,10 +1167,10 @@ export async function getChannelPerformance(request, env) {
|
|
|
1167
1167
|
|
|
1168
1168
|
## 🎯 FORMATO DE SAÍDA
|
|
1169
1169
|
|
|
1170
|
-
### DELIVERABLE 1: `attribution-engine.
|
|
1170
|
+
### DELIVERABLE 1: `modules/attribution-engine.ts`
|
|
1171
1171
|
|
|
1172
|
-
```
|
|
1173
|
-
// attribution-engine.
|
|
1172
|
+
```typescript
|
|
1173
|
+
// modules/attribution-engine.ts - Engine de atribuição multi-touch
|
|
1174
1174
|
export {
|
|
1175
1175
|
captureTouchpoint,
|
|
1176
1176
|
calculateMultiTouchAttribution,
|
|
@@ -1207,10 +1207,10 @@ CREATE INDEX IF NOT EXISTS idx_channel_source ON channel_performance(utm_source)
|
|
|
1207
1207
|
CREATE INDEX IF NOT EXISTS idx_channel_campaign ON channel_performance(utm_campaign);
|
|
1208
1208
|
```
|
|
1209
1209
|
|
|
1210
|
-
### DELIVERABLE 3: `attribution-config.
|
|
1210
|
+
### DELIVERABLE 3: `modules/attribution-config.ts`
|
|
1211
1211
|
|
|
1212
|
-
```
|
|
1213
|
-
// attribution-config.
|
|
1212
|
+
```typescript
|
|
1213
|
+
// modules/attribution-config.ts - Configuração de modelos de atribuição
|
|
1214
1214
|
export const ATTRIBUTION_CONFIG = {
|
|
1215
1215
|
default_model: 'U_SHAPE',
|
|
1216
1216
|
available_models: [
|
|
@@ -53,7 +53,7 @@ Sempre que o usuário desejar suporte Microsoft B2B/B2C High-Ticket:
|
|
|
53
53
|
```json
|
|
54
54
|
{
|
|
55
55
|
"arquivos_gerados": {
|
|
56
|
-
"server": "bing
|
|
56
|
+
"server": "modules/dispatch/bing.ts (módulo cloudflare TypeScript)"
|
|
57
57
|
},
|
|
58
58
|
"tecnologia_alvo": "Cloudflare Worker (Server-Side S2S)",
|
|
59
59
|
"api_endpoint": "https://bat.bing.com/action/0",
|
|
@@ -137,7 +137,7 @@ Regras que nunca podem ser violadas, independente do contexto:
|
|
|
137
137
|
## ESCOPO
|
|
138
138
|
|
|
139
139
|
Este agente monitora:
|
|
140
|
-
- `server-edge-tracker/
|
|
140
|
+
- `server-edge-tracker/index.ts` — código crítico de produção
|
|
141
141
|
- `extracted-skill/tracking-events-generator/cdpTrack.js` — SDK browser
|
|
142
142
|
- `extracted-skill/tracking-events-generator/agents/*.md` — definições de agentes
|
|
143
143
|
- `server-edge-tracker/wrangler.toml` — configuração de infraestrutura
|
|
@@ -183,7 +183,7 @@ CREATE INDEX IF NOT EXISTS idx_consent_policy_version
|
|
|
183
183
|
|
|
184
184
|
### Consent Collection & Storage
|
|
185
185
|
|
|
186
|
-
```
|
|
186
|
+
```typescript
|
|
187
187
|
/**
|
|
188
188
|
* Consent Manager
|
|
189
189
|
* Manages user consent collection, storage, and tracking
|
|
@@ -559,7 +559,7 @@ let consentManager = null;
|
|
|
559
559
|
|
|
560
560
|
### GDPR/LGPD/CCPA Data Rights Implementation
|
|
561
561
|
|
|
562
|
-
```
|
|
562
|
+
```typescript
|
|
563
563
|
/**
|
|
564
564
|
* Data Rights Manager
|
|
565
565
|
* Handles GDPR/LGPD/CCPA data rights: access, deletion, portability, rectification
|
|
@@ -1110,7 +1110,7 @@ let dataRightsManager = null;
|
|
|
1110
1110
|
|
|
1111
1111
|
### Automated Data Retention Policies
|
|
1112
1112
|
|
|
1113
|
-
```
|
|
1113
|
+
```typescript
|
|
1114
1114
|
/**
|
|
1115
1115
|
* Data Retention Manager
|
|
1116
1116
|
* Manages automated data retention and deletion policies
|
|
@@ -1381,7 +1381,7 @@ let dataRetentionManager = null;
|
|
|
1381
1381
|
|
|
1382
1382
|
### Comprehensive Audit Logging
|
|
1383
1383
|
|
|
1384
|
-
```
|
|
1384
|
+
```typescript
|
|
1385
1385
|
/**
|
|
1386
1386
|
* Compliance Audit Logger
|
|
1387
1387
|
* Records all compliance-related activities for audit purposes
|
|
@@ -1533,7 +1533,7 @@ let complianceAuditLogger = null;
|
|
|
1533
1533
|
|
|
1534
1534
|
### Compliance Management Endpoints
|
|
1535
1535
|
|
|
1536
|
-
```
|
|
1536
|
+
```typescript
|
|
1537
1537
|
/**
|
|
1538
1538
|
* Compliance Management Endpoints
|
|
1539
1539
|
*/
|
|
@@ -33,8 +33,8 @@ Webhook Agent (lead capturado via /track)
|
|
|
33
33
|
|
|
34
34
|
**Assinatura da função exportada (injetada no Worker):**
|
|
35
35
|
|
|
36
|
-
```
|
|
37
|
-
// Injetada no
|
|
36
|
+
```typescript
|
|
37
|
+
// Injetada no index.ts pelo CRM Integration Agent
|
|
38
38
|
export async function syncToCRM(env, eventType, payload) {
|
|
39
39
|
// eventType: 'lead' | 'purchase' | 'checkout_abandoned'
|
|
40
40
|
// payload: { email, name, product, value, order_id, phone }
|
|
@@ -67,7 +67,7 @@ Implementar **integração bidirecional** entre CDP Edge D1 e CRMs externos, per
|
|
|
67
67
|
|
|
68
68
|
### 1.1 Tipos de CRM Suportados
|
|
69
69
|
|
|
70
|
-
```
|
|
70
|
+
```typescript
|
|
71
71
|
// CRMs suportados com mapeamentos
|
|
72
72
|
export const SUPPORTED_CRMS = {
|
|
73
73
|
HUBSPOT: {
|
|
@@ -188,7 +188,7 @@ export function configureCRM(crmType, config) {
|
|
|
188
188
|
|
|
189
189
|
### 2.1 Mapeamento de Leads
|
|
190
190
|
|
|
191
|
-
```
|
|
191
|
+
```typescript
|
|
192
192
|
// Mapeamento de campos de lead do D1 para cada CRM
|
|
193
193
|
export const LEAD_FIELD_MAPPINGS = {
|
|
194
194
|
HUBSPOT: {
|
|
@@ -439,7 +439,7 @@ function extractLastName(fullName) {
|
|
|
439
439
|
|
|
440
440
|
### 2.2 Mapeamento de Compras (Conversões)
|
|
441
441
|
|
|
442
|
-
```
|
|
442
|
+
```typescript
|
|
443
443
|
// Mapeamento de campos de purchase para cada CRM
|
|
444
444
|
export const PURCHASE_FIELD_MAPPINGS = {
|
|
445
445
|
HUBSPOT: {
|
|
@@ -642,7 +642,7 @@ export const PURCHASE_FIELD_MAPPINGS = {
|
|
|
642
642
|
|
|
643
643
|
### 3.1 Sync de Leads (Batch)
|
|
644
644
|
|
|
645
|
-
```
|
|
645
|
+
```typescript
|
|
646
646
|
// Sincronizar leads do D1 para CRM em batch
|
|
647
647
|
export async function syncLeadsToCRM(env, hours = 24, batchSize = 50) {
|
|
648
648
|
const leads = await env.DB.prepare(`
|
|
@@ -741,7 +741,7 @@ async function markLeadAsSynced(leadId, env) {
|
|
|
741
741
|
|
|
742
742
|
### 3.2 Sync de Compras (Batch)
|
|
743
743
|
|
|
744
|
-
```
|
|
744
|
+
```typescript
|
|
745
745
|
// Sincronizar compras do D1 para CRM em batch
|
|
746
746
|
export async function syncPurchasesToCRM(env, hours = 24, batchSize = 20) {
|
|
747
747
|
const purchases = await env.DB.prepare(`
|
|
@@ -846,7 +846,7 @@ async function markPurchaseAsSynced(purchaseId, env) {
|
|
|
846
846
|
|
|
847
847
|
### 4.1 Webhook Endpoint para Atualizações do CRM
|
|
848
848
|
|
|
849
|
-
```
|
|
849
|
+
```typescript
|
|
850
850
|
// Endpoint para receber webhooks do CRM
|
|
851
851
|
export async function handleCRMWebhook(request, env) {
|
|
852
852
|
const payload = await request.json();
|
|
@@ -929,7 +929,7 @@ function validateWebhookSignature(payload, signature, crmType) {
|
|
|
929
929
|
|
|
930
930
|
### 5.1 Schedule Config (Batch vs Real-time)
|
|
931
931
|
|
|
932
|
-
```
|
|
932
|
+
```typescript
|
|
933
933
|
// Configuração de como a sincronização deve funcionar
|
|
934
934
|
export const SYNC_CONFIG = {
|
|
935
935
|
mode: 'BATCH', // ou 'REAL-TIME'
|
|
@@ -993,7 +993,7 @@ export const CRM_SPECIFIC_CONFIG = {
|
|
|
993
993
|
|
|
994
994
|
### DELIVERABLE 1: `crm-webhook-handlers.js`
|
|
995
995
|
|
|
996
|
-
```
|
|
996
|
+
```typescript
|
|
997
997
|
// Funções para Cloudflare Worker - Webhooks do CRM
|
|
998
998
|
import { validateWebhookSignature, updateLeadStageFromCRM, updateDealStatusFromCRM, updateLeadScoreFromCRM } from './crm-sync.js';
|
|
999
999
|
|
|
@@ -94,7 +94,7 @@ Definir o Dashboard como um **Centro de Comando de Dados** que equilibra:
|
|
|
94
94
|
- Dados de evento: 15 minutos
|
|
95
95
|
|
|
96
96
|
**Implementação:**
|
|
97
|
-
```
|
|
97
|
+
```typescript
|
|
98
98
|
// Carregar dados do cache
|
|
99
99
|
const fetchMetrics = async (env, forceRefresh = false) => {
|
|
100
100
|
const cacheKey = 'dashboard_metrics';
|
|
@@ -129,7 +129,7 @@ const fetchMetrics = async (env, forceRefresh = false) => {
|
|
|
129
129
|
- Desativação manual ou timeout de inatividade
|
|
130
130
|
|
|
131
131
|
**Implementação:**
|
|
132
|
-
```
|
|
132
|
+
```typescript
|
|
133
133
|
const useRealTime = async () => {
|
|
134
134
|
// WebSockets ou Server-Sent Events (SSE)
|
|
135
135
|
const eventSource = new EventSource('/api/metrics/stream');
|
|
@@ -187,7 +187,7 @@ Invalidação:
|
|
|
187
187
|
|
|
188
188
|
### Para Cloudflare Worker
|
|
189
189
|
|
|
190
|
-
```
|
|
190
|
+
```typescript
|
|
191
191
|
// ENDPOINTS DE CONSULTA (otimizados)
|
|
192
192
|
export const DASHBOARD_API = {
|
|
193
193
|
// Métricas globais (cache no KV)
|
|
@@ -44,7 +44,7 @@ Deploy: (data do último deploy)
|
|
|
44
44
|
### `wrangler.toml` — Estado Real
|
|
45
45
|
```toml
|
|
46
46
|
name = "server-edge-tracker"
|
|
47
|
-
main = "
|
|
47
|
+
main = "index.ts"
|
|
48
48
|
compatibility_date = "2025-01-01"
|
|
49
49
|
compatibility_flags = ["nodejs_compat"]
|
|
50
50
|
|
|
@@ -78,7 +78,7 @@ crons = ["0 2 * * 7", "0 3 1 * *"]
|
|
|
78
78
|
- **ID:** `SEU_D1_DATABASE_ID`
|
|
79
79
|
- **Região:** ENAM (US East)
|
|
80
80
|
- **Engine:** SQLite (Cloudflare D1)
|
|
81
|
-
- **Tabelas ativas:**
|
|
81
|
+
- **Tabelas ativas:** 31 (core: 13, migrate-v6: 1, migrate-v7: 2, Fases 1-4: 10, schema-ltv-feedback: +3 colunas, schema-utm: 1, schema-quiz: 1, schema-sales-engine: 3)
|
|
82
82
|
|
|
83
83
|
### Schema Completo (Produção)
|
|
84
84
|
|
|
@@ -259,7 +259,7 @@ CREATE INDEX IF NOT EXISTS idx_wa_ctwa_clid ON whatsapp_contacts(ctwa_clid);
|
|
|
259
259
|
CREATE INDEX IF NOT EXISTS idx_wa_created_at ON whatsapp_contacts(created_at);
|
|
260
260
|
```
|
|
261
261
|
> **Migration:** `migrate-v6.sql` — aplicar com `wrangler d1 execute cdp-edge-db --file=migrate-v6.sql --remote`
|
|
262
|
-
> **Tabelas ativas após v6:** 14 (core: 13 + whatsapp_contacts)
|
|
262
|
+
> **Tabelas ativas após v6:** 14 (core: 13 + whatsapp_contacts). Total final após todos os schemas: 31 tabelas.
|
|
263
263
|
|
|
264
264
|
---
|
|
265
265
|
|
|
@@ -280,7 +280,7 @@ CREATE TABLE intelligence_logs (
|
|
|
280
280
|
```
|
|
281
281
|
|
|
282
282
|
### Padrões de Acesso D1 no Worker
|
|
283
|
-
```
|
|
283
|
+
```typescript
|
|
284
284
|
// SELECT com bind (previne SQL injection)
|
|
285
285
|
const { results } = await env.DB
|
|
286
286
|
.prepare('SELECT * FROM leads WHERE email = ? ORDER BY created_at DESC LIMIT 1')
|
|
@@ -339,7 +339,7 @@ wrangler queues create cdp-edge-dlq
|
|
|
339
339
|
```
|
|
340
340
|
|
|
341
341
|
### Uso no Worker (Produtor)
|
|
342
|
-
```
|
|
342
|
+
```typescript
|
|
343
343
|
// Enfileirar evento com falha para retry
|
|
344
344
|
await env.RETRY_QUEUE.send({
|
|
345
345
|
platform: 'meta',
|
|
@@ -351,7 +351,7 @@ await env.RETRY_QUEUE.send({
|
|
|
351
351
|
```
|
|
352
352
|
|
|
353
353
|
### Handler do Consumidor
|
|
354
|
-
```
|
|
354
|
+
```typescript
|
|
355
355
|
export default {
|
|
356
356
|
async queue(batch, env) {
|
|
357
357
|
for (const msg of batch.messages) {
|
|
@@ -406,7 +406,7 @@ wrangler kv namespace create GEO_CACHE
|
|
|
406
406
|
```
|
|
407
407
|
|
|
408
408
|
### Uso no Worker
|
|
409
|
-
```
|
|
409
|
+
```typescript
|
|
410
410
|
// Cache de geolocalização por IP (TTL: 1 hora)
|
|
411
411
|
const cacheKey = `geo:${clientIp}`;
|
|
412
412
|
let geoData = await env.GEO_CACHE.get(cacheKey, { type: 'json' });
|
|
@@ -448,7 +448,7 @@ wrangler r2 bucket create cdp-edge-logs
|
|
|
448
448
|
```
|
|
449
449
|
|
|
450
450
|
### Uso no Worker
|
|
451
|
-
```
|
|
451
|
+
```typescript
|
|
452
452
|
// Armazenar evento bruto para auditoria (LGPD)
|
|
453
453
|
const logKey = `events/${year}/${month}/${day}/${eventId}.json`;
|
|
454
454
|
await env.AUDIT_LOGS.put(logKey, JSON.stringify({
|
|
@@ -474,7 +474,7 @@ Limite Free: 10.000 neurônios/dia (~350 predições/dia com Granite)
|
|
|
474
474
|
```
|
|
475
475
|
|
|
476
476
|
### Uso no Worker (LTV Prediction)
|
|
477
|
-
```
|
|
477
|
+
```typescript
|
|
478
478
|
async function predictLtv(leadData, env) {
|
|
479
479
|
if (!env.AI) return { ltv_class: 'unknown', ltv_value: 0 };
|
|
480
480
|
|
|
@@ -510,7 +510,7 @@ async function predictLtv(leadData, env) {
|
|
|
510
510
|
| `0 3 1 * *` | Dia 1 03:00 | Intelligence Agent — auditoria mensal de erros |
|
|
511
511
|
|
|
512
512
|
### Handler no Worker
|
|
513
|
-
```
|
|
513
|
+
```typescript
|
|
514
514
|
export default {
|
|
515
515
|
async scheduled(event, env, ctx) {
|
|
516
516
|
ctx.waitUntil(runIntelligenceAgent(event.cron, env));
|
|
@@ -573,7 +573,7 @@ wrangler secret put RESEND_FROM_EMAIL
|
|
|
573
573
|
|
|
574
574
|
Todo I/O que não bloqueia a resposta ao browser **DEVE** usar `ctx.waitUntil`:
|
|
575
575
|
|
|
576
|
-
```
|
|
576
|
+
```typescript
|
|
577
577
|
export default {
|
|
578
578
|
async fetch(request, env, ctx) {
|
|
579
579
|
|
|
@@ -601,20 +601,12 @@ export default {
|
|
|
601
601
|
|
|
602
602
|
## 🗺️ ROADMAP DE INFRAESTRUTURA
|
|
603
603
|
|
|
604
|
-
### Fase Atual (✅ Implementado)
|
|
605
|
-
- D1 com
|
|
606
|
-
- Workers AI
|
|
607
|
-
- 2 Cron Triggers ativos
|
|
608
|
-
-
|
|
609
|
-
|
|
610
|
-
### Fase 2 (🔧 Próximos Passos)
|
|
611
|
-
- Queues para retry robusto (substituir retry síncrono atual)
|
|
612
|
-
- KV para cache de geo/sessão (reduzir latência)
|
|
613
|
-
|
|
614
|
-
### Fase 3 (🚀 Enterprise)
|
|
615
|
-
- R2 para logs auditáveis (conformidade LGPD)
|
|
616
|
-
- Múltiplos Workers especializados (routing por subdomínio)
|
|
617
|
-
- Durable Objects para sessões real-time
|
|
604
|
+
### Fase Atual (✅ Implementado — v2.5.1)
|
|
605
|
+
- D1 com 31 tabelas em produção (core + Fases 1-7)
|
|
606
|
+
- Workers AI: Granite 4.0 Micro (LTV + Quiz Scoring) + bge-m3 (Clustering)
|
|
607
|
+
- 2 Cron Triggers ativos (semanal + mensal)
|
|
608
|
+
- Rate Limiter, KV, R2 Audit Logs, Queues configurados
|
|
609
|
+
- Quiz Scoring Engine + Nurture Engine + ROAS Feedback Loop ativos
|
|
618
610
|
|
|
619
611
|
---
|
|
620
612
|
|