@jussimirvfx/meta-pixel-tracking
Version:
Sistema completo de tracking do Meta Pixel (Pixel + CAPI) com proteção anti-adblock para landing pages
1 lines • 124 kB
Source Map (JSON)
{"version":3,"file":"index.cjs","sources":["../src/lib/config/meta-pixel.ts","../src/lib/utils/logger.ts","../src/lib/facebook-pixel-init.ts","../__vite-browser-external","../node_modules/crypto-js/core.js","../node_modules/crypto-js/sha256.js","../src/lib/utils/hash.ts","../src/lib/utils/cookies.ts","../src/lib/hooks/use-meta-pixel.ts","../src/components/providers/meta-pixel-provider.tsx","../src/lib/hooks/use-scroll-tracking.ts","../src/components/analytics/meta-pixel.tsx"],"sourcesContent":["// Tipagem da configuração\nexport interface MetaPixelConfig {\n PIXEL_ID: string;\n ACCESS_TOKEN: string;\n TEST_EVENT_CODE?: string;\n DEDUPLICATION?: {\n MAX_AGE_HOURS: number;\n };\n UNIVERSAL_PARAMETERS: string[];\n STANDARD_EVENTS: string[];\n VERBOSE?: boolean;\n}\n\n// Flag para controlar se já foi configurado\nlet isConfigured = false;\n\n/**\n * Detecta se está em ambiente Vercel e ativa debug automaticamente\n */\nfunction detectVercelAndEnableDebug(): boolean {\n if (typeof window === 'undefined') return false;\n \n const url = window.location.href;\n const isVercel = url.includes('vercel.app') || url.includes('vercel.com');\n \n if (isVercel) {\n console.log('[META PIXEL] 🚀 Detectado ambiente Vercel, ativando debug automático');\n return true;\n }\n \n return false;\n}\n\n// Configuração padrão\nexport let META_PIXEL_CONFIG: MetaPixelConfig = {\n PIXEL_ID: '',\n ACCESS_TOKEN: '',\n TEST_EVENT_CODE: '',\n DEDUPLICATION: {\n MAX_AGE_HOURS: 24,\n },\n UNIVERSAL_PARAMETERS: [\n 'event_time',\n 'event_source_url',\n 'page_title',\n 'page_path',\n 'browser_language',\n 'screen_width',\n 'screen_height',\n 'viewport_width',\n 'viewport_height',\n 'timezone',\n 'referrer',\n ],\n STANDARD_EVENTS: [\n 'PageView',\n 'Lead',\n 'LeadQualificado',\n ],\n VERBOSE: false,\n};\n\n// Função para verificar se está configurado\nexport function isMetaPixelConfigured(): boolean {\n return isConfigured && !!META_PIXEL_CONFIG.PIXEL_ID && !!META_PIXEL_CONFIG.ACCESS_TOKEN;\n}\n\n// Função para validar configuração obrigatória\nexport function validateConfiguration(): void {\n if (!META_PIXEL_CONFIG.PIXEL_ID) {\n throw new Error('PIXEL_ID é obrigatório. Configure usando configureMetaPixel()');\n }\n if (!META_PIXEL_CONFIG.ACCESS_TOKEN) {\n throw new Error('ACCESS_TOKEN é obrigatório. Configure usando configureMetaPixel()');\n }\n}\n\n// Função para configurar o Meta Pixel\nexport function configureMetaPixel(config: Partial<MetaPixelConfig>) {\n META_PIXEL_CONFIG = { ...META_PIXEL_CONFIG, ...config };\n isConfigured = true;\n \n // Detectar Vercel e ativar debug automaticamente\n const isVercel = detectVercelAndEnableDebug();\n \n // Ativar debug se estiver em Vercel ou development/preview\n if (isVercel || (typeof window !== 'undefined' && (import.meta.env.MODE === 'development' || import.meta.env.MODE === 'preview'))) {\n META_PIXEL_CONFIG.VERBOSE = true;\n console.log('[META PIXEL] 🔍 Debug ativado automaticamente');\n }\n \n // Validar configuração\n if (!config.PIXEL_ID) {\n console.error('⚠️ PIXEL_ID não fornecido na configuração');\n }\n if (!config.ACCESS_TOKEN) {\n console.error('⚠️ ACCESS_TOKEN não fornecido na configuração');\n }\n \n // Debug simplificado após configuração\n if (META_PIXEL_CONFIG.VERBOSE) {\n console.log('[META PIXEL CONFIGURADO]', {\n PIXEL_ID: META_PIXEL_CONFIG.PIXEL_ID ? 'Configurado' : 'Não configurado',\n ACCESS_TOKEN: META_PIXEL_CONFIG.ACCESS_TOKEN ? 'Configurado' : 'Não configurado',\n TEST_EVENT_CODE: META_PIXEL_CONFIG.TEST_EVENT_CODE || 'Não configurado',\n VERBOSE: META_PIXEL_CONFIG.VERBOSE,\n ENVIRONMENT: isVercel ? 'Vercel' : import.meta.env.MODE\n });\n }\n \n if (typeof window !== 'undefined') {\n (window as any)._metaPixelDebug = {\n getConfig: () => META_PIXEL_CONFIG,\n isConfigured: () => isMetaPixelConfigured(),\n validate: validateConfiguration\n };\n }\n}\n\n // Debug imediato para desenvolvedores (apenas se não configurado)\n if (typeof window !== 'undefined' && (import.meta.env.MODE === 'development' || import.meta.env.MODE === 'preview')) {\n // Aguardar um microtask para dar tempo de configuração\n Promise.resolve().then(() => {\n if (!isMetaPixelConfigured()) {\n console.warn('[META PIXEL NÃO CONFIGURADO] Package não configurado. Use configureMetaPixel() antes de usar o hook.');\n }\n });\n \n (window as any)._metaPixelDebug = {\n getConfig: () => META_PIXEL_CONFIG,\n isConfigured: () => isMetaPixelConfigured(),\n validate: validateConfiguration\n };\n}\n\nexport type StandardEvent = (typeof META_PIXEL_CONFIG.STANDARD_EVENTS)[number]; ","// Sistema de logging para o Meta Pixel\n\nexport enum LogCategory {\n INIT = 'INIT',\n META_PIXEL = 'META_PIXEL',\n CONVERSION_API = 'CONVERSION_API',\n PAGE_VIEW = 'PAGE_VIEW',\n SCROLL = 'SCROLL',\n LEAD = 'LEAD',\n QUALIFIED_LEAD = 'QUALIFIED_LEAD',\n VIDEO = 'VIDEO',\n ERROR = 'ERROR',\n DEBUG = 'DEBUG'\n}\n\nexport enum LogLevel {\n DEBUG = 0,\n INFO = 1,\n WARN = 2,\n ERROR = 3\n}\n\ninterface LogEntry {\n timestamp: number\n level: LogLevel\n category: LogCategory\n message: string\n data?: any\n}\n\nclass Logger {\n private logs: LogEntry[] = []\n private maxLogs = 1000\n\n // Função para detectar se deve mostrar logs\n private shouldShowLogs(): boolean {\n // Verificar se estamos no navegador\n if (typeof window === 'undefined') return false\n \n // Verificar configuração VERBOSE do Meta Pixel\n try {\n // Verificar se há configuração VERBOSE no window\n if ((window as any)._metaPixelDebug?.getConfig?.()?.VERBOSE) {\n return true;\n }\n } catch (error) {\n // Se não conseguir verificar, continuar com outras verificações\n }\n \n // Verificar se estamos em desenvolvimento\n const isDev = \n // Vite development\n (typeof import.meta !== 'undefined' && import.meta.env?.MODE === 'development') ||\n // Vite preview\n (typeof import.meta !== 'undefined' && import.meta.env?.MODE === 'preview') ||\n // Node.js development\n process.env.NODE_ENV === 'development' ||\n // Verificar se há debug ativo\n window.location.hostname === 'localhost' ||\n window.location.hostname === '127.0.0.1' ||\n // Verificar se há parâmetro de debug na URL\n window.location.search.includes('debug=true') ||\n // Verificar se há localStorage com debug ativo\n localStorage.getItem('meta-pixel-debug') === 'true' ||\n // Verificar se há console aberto (método simples)\n window.outerHeight - window.innerHeight > 200\n\n return isDev\n }\n\n private addLog(level: LogLevel, category: LogCategory, message: string, data?: any) {\n const entry: LogEntry = {\n timestamp: Date.now(),\n level,\n category,\n message,\n data\n }\n\n this.logs.push(entry)\n\n // Manter apenas os últimos logs\n if (this.logs.length > this.maxLogs) {\n this.logs = this.logs.slice(-this.maxLogs)\n }\n\n // Expor logs no console em desenvolvimento\n if (this.shouldShowLogs()) {\n const prefix = `[META PIXEL - ${category}]`\n const timestamp = new Date().toLocaleTimeString()\n\n switch (level) {\n case LogLevel.DEBUG:\n console.debug(`${prefix} ${timestamp} - ${message}`, data || '')\n break\n case LogLevel.INFO:\n console.info(`${prefix} ${timestamp} - ${message}`, data || '')\n break\n case LogLevel.WARN:\n console.warn(`${prefix} ${timestamp} - ${message}`, data || '')\n break\n case LogLevel.ERROR:\n console.error(`${prefix} ${timestamp} - ${message}`, data || '')\n break\n }\n }\n\n // Expor logs globalmente para debug (sempre disponível)\n if (typeof window !== 'undefined') {\n if (!window._metaPixelLogs) {\n window._metaPixelLogs = {\n getLogs: () => this.logs,\n getLogsByCategory: (category: string) => this.logs.filter(log => log.category === category),\n clear: () => { this.logs = [] },\n enable: () => { localStorage.setItem('meta-pixel-debug', 'true') },\n disable: () => { localStorage.removeItem('meta-pixel-debug') },\n isEnabled: () => this.shouldShowLogs()\n }\n }\n }\n }\n\n debug(category: LogCategory, message: string, data?: any) {\n this.addLog(LogLevel.DEBUG, category, message, data)\n }\n\n info(category: LogCategory, message: string, data?: any) {\n this.addLog(LogLevel.INFO, category, message, data)\n }\n\n warn(category: LogCategory, message: string, data?: any) {\n this.addLog(LogLevel.WARN, category, message, data)\n }\n\n error(category: LogCategory, message: string, data?: any) {\n this.addLog(LogLevel.ERROR, category, message, data)\n }\n\n // Métodos específicos para eventos principais\n pageView(eventId: string, params: any) {\n this.info(LogCategory.PAGE_VIEW, 'PageView enviado', {\n eventId,\n pageTitle: params.page_title,\n pagePath: params.page_path,\n hasUserData: !!params.user_data,\n userData: {\n hasEmail: !!params.user_data?.em,\n hasPhone: !!params.user_data?.ph,\n hasName: !!(params.user_data?.fn || params.user_data?.ln),\n hasFbc: !!params.user_data?.fbc,\n hasFbp: !!params.user_data?.fbp\n }\n })\n }\n\n scroll(depth: number, eventId: string, params: any) {\n this.info(LogCategory.SCROLL, `Scroll atingiu ${depth}%`, {\n eventId,\n depth,\n scrollPercentage: params.scroll_percentage,\n scrollY: params.scroll_y,\n pageTitle: params.page_title,\n pagePath: params.page_path\n })\n }\n\n lead(eventId: string, params: any, userData: any) {\n this.info(LogCategory.LEAD, 'Lead enviado', {\n eventId,\n value: params.value,\n currency: params.currency,\n contentName: params.content_name,\n hasUserData: true,\n userData: {\n hasEmail: !!userData?.em,\n hasPhone: !!userData?.ph,\n hasName: !!(userData?.fn || userData?.ln),\n hasFbc: !!userData?.fbc,\n hasFbp: !!userData?.fbp\n },\n processedUserData: {\n hasEmailHash: !!userData?.em,\n hasPhoneHash: !!userData?.ph,\n hasNameHash: !!(userData?.fn || userData?.ln)\n }\n })\n }\n\n leadQualificado(eventId: string, params: any, userData: any) {\n this.info(LogCategory.QUALIFIED_LEAD, 'LeadQualificado enviado', {\n eventId,\n value: params.value,\n currency: params.currency,\n contentName: params.content_name,\n leadScore: params.lead_score,\n qualificationStatus: params.qualification_status,\n hasUserData: true,\n userData: {\n hasEmail: !!userData?.em,\n hasPhone: !!userData?.ph,\n hasName: !!(userData?.fn || userData?.ln),\n hasFbc: !!userData?.fbc,\n hasFbp: !!userData?.fbp\n }\n })\n }\n\n pixelEvent(eventName: string, eventId: string, method: 'track' | 'trackCustom', success: boolean) {\n this.info(LogCategory.META_PIXEL, `Evento enviado via Pixel: ${eventName}`, {\n eventId,\n method,\n success\n })\n }\n\n conversionApiEvent(eventName: string, eventId: string, success: boolean, responseTime?: number) {\n this.info(LogCategory.CONVERSION_API, `Evento enviado via API: ${eventName}`, {\n eventId,\n success,\n responseTime: responseTime ? `${Math.round(responseTime)}ms` : undefined\n })\n }\n\n getLogs(): LogEntry[] {\n return [...this.logs]\n }\n\n getLogsByCategory(category: LogCategory): LogEntry[] {\n return this.logs.filter(log => log.category === category)\n }\n\n clear(): void {\n this.logs = []\n }\n}\n\nconst logger = new Logger()\nexport default logger ","// Inicialização do Facebook Pixel para Vite com proteção anti-adblock\n\nimport { META_PIXEL_CONFIG } from './config/meta-pixel'\nimport logger, { LogCategory } from './utils/logger'\n\nlet isInitialized = false\n\n// Lista de eventos padrão do Facebook Pixel\nconst STANDARD_EVENTS = [\n \"PageView\",\n \"Lead\",\n \"LeadQualificado\",\n]\n\n// Configuração anti-adblock (para futuras expansões)\n// const ANTI_ADBLOCK_CONFIG = {\n// // Nomes ofuscados para evitar detecção\n// scriptNames: ['analytics.js', 'stats.js', 'metrics.js', 'tracking.js'],\n// functionNames: ['analytics', 'stats', 'metrics', 'track'],\n// // URLs de proxy local para o script do Facebook\n// proxyUrls: [\n// '/assets/fb-pixel.js',\n// '/public/analytics.js',\n// '/static/tracking.js'\n// ]\n// }\n\n/**\n * Cria um proxy local para o script do Facebook\n */\nfunction createFacebookPixelProxy(): void {\n if (typeof window === 'undefined') return\n\n // Criar conteúdo do script ofuscado\n const fbPixelCode = `\n !function(f,b,e,v,n,t,s)\n {if(f.fbq)return;n=f.fbq=function(){n.callMethod?\n n.callMethod.apply(n,arguments):n.queue.push(arguments)};\n if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';\n n.queue=[];}(window,document,'script','');\n \n // Carregar o script real do Facebook de forma assíncrona\n (function() {\n var script = document.createElement('script');\n script.async = true;\n script.src = 'https://connect.facebook.net/en_US/fbevents.js';\n script.onerror = function() {\n // Fallback: tentar outros CDNs\n var fallbackScript = document.createElement('script');\n fallbackScript.async = true;\n fallbackScript.src = 'https://cdn.fbsbx.com/en_US/fbevents.js';\n document.head.appendChild(fallbackScript);\n };\n document.head.appendChild(script);\n })();\n `\n\n // Criar blob e URL para o script\n const blob = new Blob([fbPixelCode], { type: 'application/javascript' })\n const scriptUrl = URL.createObjectURL(blob)\n\n // Carregar o script proxy\n const script = document.createElement('script')\n script.async = true\n script.src = scriptUrl\n script.onload = () => {\n logger.info(LogCategory.INIT, \"Script do Facebook carregado via proxy anti-adblock\")\n window._fbPixelScriptLoaded = true\n // Limpar URL do blob após carregar\n URL.revokeObjectURL(scriptUrl)\n }\n script.onerror = () => {\n logger.warn(LogCategory.INIT, \"Proxy falhou, tentando método direto\")\n loadFacebookPixelScriptDirect()\n }\n \n document.head.appendChild(script)\n}\n\n/**\n * Carrega o script do Facebook diretamente (fallback)\n */\nfunction loadFacebookPixelScriptDirect(): void {\n if (typeof window === 'undefined') return\n \n const script = document.createElement('script')\n script.async = true\n script.src = 'https://connect.facebook.net/en_US/fbevents.js'\n script.onload = () => {\n logger.info(LogCategory.INIT, \"Script do Facebook carregado diretamente\")\n window._fbPixelScriptLoaded = true\n }\n script.onerror = (error) => {\n logger.error(LogCategory.INIT, \"Erro ao carregar script do Facebook\", { error })\n // Último recurso: tentar CDN alternativo\n loadFacebookPixelAlternativeCDN()\n }\n \n document.head.appendChild(script)\n}\n\n/**\n * Tenta CDN alternativo do Facebook (último recurso)\n */\nfunction loadFacebookPixelAlternativeCDN(): void {\n if (typeof window === 'undefined') return\n \n const script = document.createElement('script')\n script.async = true\n script.src = 'https://cdn.fbsbx.com/en_US/fbevents.js'\n script.onload = () => {\n logger.info(LogCategory.INIT, \"Script do Facebook carregado via CDN alternativo\")\n window._fbPixelScriptLoaded = true\n }\n script.onerror = (error) => {\n logger.error(LogCategory.INIT, \"Todos os métodos de carregamento falharam\", { error })\n }\n \n document.head.appendChild(script)\n}\n\n/**\n * Inicializa o fbq mesmo se o script não carregar (modo offline)\n */\nfunction initFacebookPixelOffline(): void {\n if (typeof window === 'undefined') return\n\n // Criar implementação mínima do fbq para casos onde o script é bloqueado\n if (!window.fbq) {\n window.fbq = function(...args: any[]) {\n // Armazenar eventos para envio posterior via API\n if (!window._fbq_calls) window._fbq_calls = []\n window._fbq_calls.push(args)\n \n // Log dos eventos mesmo quando bloqueado\n if (args.length >= 2) {\n const [command, eventName] = args\n logger.info(LogCategory.META_PIXEL, `Evento ${eventName} armazenado (script bloqueado)`, {\n command,\n args: args.slice(2)\n })\n }\n }\n\n if (!window._fbq) window._fbq = window.fbq\n ;(window.fbq as any).push = window.fbq\n ;(window.fbq as any).loaded = true\n ;(window.fbq as any).version = \"2.0-offline\"\n ;(window.fbq as any).queue = []\n\n logger.warn(LogCategory.INIT, \"Facebook Pixel inicializado em modo offline (script bloqueado)\")\n }\n}\n\n// Função para inicializar o Facebook Pixel\nexport function initFacebookPixel(): void {\n // Verificar se estamos no lado do cliente\n if (typeof window === \"undefined\") return\n\n // Debug simplificado para identificar conflitos\n if (import.meta.env.MODE === 'development' || import.meta.env.MODE === 'preview') {\n console.log('[META PIXEL INIT] Status:', {\n isInitialized,\n fbPixelInitialized: window._fbPixelInitialized,\n fbqExists: !!window.fbq,\n pixelId: META_PIXEL_CONFIG.PIXEL_ID ? 'Configurado' : 'Não configurado'\n });\n }\n\n // Verificar se já foi inicializado globalmente\n if (isInitialized || window._fbPixelInitialized) {\n logger.debug(LogCategory.INIT, \"Facebook Pixel já inicializado, pulando...\")\n isInitialized = true\n return\n }\n\n // Marcar como inicializado\n isInitialized = true\n window._fbPixelInitialized = true\n\n logger.info(LogCategory.INIT, \"Iniciando Facebook Pixel com proteção anti-adblock...\")\n\n // Tentar carregar script com proteção anti-adblock primeiro\n if (!window._fbPixelScriptLoaded) {\n createFacebookPixelProxy()\n \n // Timeout para detectar se o script foi bloqueado\n setTimeout(() => {\n if (!window.fbq || typeof window.fbq !== 'function') {\n logger.warn(LogCategory.INIT, \"Script detectado como bloqueado, inicializando modo offline\")\n initFacebookPixelOffline()\n }\n }, 3000)\n }\n\n // Inicializar o objeto fbq se ainda não existe\n if (!window.fbq) {\n window.fbq = function(...args: any[]) {\n // Verificar se há argumentos\n if (args.length === 0) {\n logger.warn(LogCategory.META_PIXEL, \"Tentativa de chamar fbq() sem argumentos\")\n return\n }\n\n if ((window.fbq as any).callMethod) {\n (window.fbq as any).callMethod.apply(window.fbq, args)\n } else {\n (window.fbq as any).queue.push(args)\n }\n }\n\n if (!window._fbq) window._fbq = window.fbq\n ;(window.fbq as any).push = window.fbq\n ;(window.fbq as any).loaded = true\n ;(window.fbq as any).version = \"2.0\"\n ;(window.fbq as any).queue = []\n }\n\n // Obter o ID do Pixel da configuração\n const pixelId = META_PIXEL_CONFIG.PIXEL_ID\n \n // Debug simplificado da inicialização\n if (import.meta.env.MODE === 'development' || import.meta.env.MODE === 'preview') {\n console.log('[META PIXEL INIT] Inicializando com Pixel ID:', pixelId ? 'Configurado' : 'Não configurado');\n }\n \n // Registrar um evento para garantir que o script seja utilizado\n window.fbq(\"init\", pixelId)\n\n // Não rastrear PageView automaticamente, isso será feito pelo componente\n logger.info(LogCategory.INIT, `Facebook Pixel inicializado ${pixelId} com proteção anti-adblock`)\n\n // Definir a função global de rastreamento\n if (!window.trackFBEvent) {\n window.trackFBEvent = (event, params) => {\n if (window.fbq) {\n // Extrair event_id dos parâmetros se presente\n const { event_id, ...otherParams } = params || {}\n \n // Preparar opções com eventID no formato correto\n const options = event_id ? { eventID: event_id } : {}\n \n // Verificar se é um evento padrão ou personalizado\n if (STANDARD_EVENTS.includes(event)) {\n window.fbq(\"track\", event, otherParams, options)\n } else {\n window.fbq(\"trackCustom\", event, otherParams, options)\n }\n return true\n }\n return false\n }\n logger.info(LogCategory.INIT, \"Função global de rastreamento registrada\")\n }\n}\n\n// Função para rastrear eventos\nexport function trackPixelEvent(eventName: string, params?: any, leadData?: any): boolean {\n // Verificar se estamos no lado do cliente\n if (typeof window === \"undefined\") return false\n\n // Inicializar o pixel se ainda não foi feito\n if (!isInitialized) {\n initFacebookPixel()\n }\n\n // Gerar um ID de evento único para deduplicação\n const eventId = `evt_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`\n\n // Obter FBC e FBP para incluir nos parâmetros\n const fbc = document.cookie.match(/_fbc=([^;]+)/)?.pop() || null\n const fbp = document.cookie.match(/_fbp=([^;]+)/)?.pop() || null\n\n // Adicionar FBC, FBP e eventId aos parâmetros\n const enhancedParams = {\n ...params,\n _fbc: fbc || undefined,\n _fbp: fbp || undefined,\n event_id: eventId,\n }\n\n logger.info(LogCategory.META_PIXEL, `Rastreando evento: ${eventName}`, {\n eventId,\n hasParams: !!params,\n hasLeadData: !!leadData,\n fbqAvailable: !!window.fbq\n })\n\n // Usar a função global de rastreamento\n if (window.trackFBEvent) {\n return window.trackFBEvent(eventName, enhancedParams)\n } else if (window.fbq) {\n // Extrair o event_id dos parâmetros para usar no formato correto\n const { event_id, ...otherParams } = enhancedParams\n\n // Preparar opções com eventID no formato correto\n const options = event_id ? { eventID: event_id } : {}\n\n // Verificar se é um evento padrão ou personalizado\n if (STANDARD_EVENTS.includes(eventName)) {\n window.fbq(\"track\", eventName, otherParams, options)\n } else {\n window.fbq(\"trackCustom\", eventName, otherParams, options)\n }\n return true\n }\n\n // Se chegou aqui, o fbq não está disponível (bloqueado)\n logger.warn(LogCategory.META_PIXEL, `Evento ${eventName} não pôde ser enviado via pixel (bloqueado)`, {\n eventId,\n willSendViaAPI: true\n })\n\n return false\n}\n\n// Função para verificar se o pixel está inicializado\nexport function isPixelInitialized(): boolean {\n return isInitialized && !!window.fbq\n}\n\n// Função para carregar o script do Facebook com proteção anti-adblock\nexport function loadFacebookPixelScript(): void {\n if (typeof window === \"undefined\") return\n \n // Verificar se o script já foi carregado\n if (window._fbPixelScriptLoaded) {\n logger.debug(LogCategory.INIT, \"Script do Facebook já carregado\")\n return\n }\n\n logger.info(LogCategory.INIT, \"Carregando script do Facebook com proteção anti-adblock\")\n \n // Tentar método anti-adblock primeiro\n createFacebookPixelProxy()\n}\n\n// Função para verificar se o pixel está sendo bloqueado\nexport function isPixelBlocked(): boolean {\n if (typeof window === 'undefined') return false\n \n // Verificar se o fbq existe e funciona\n if (!window.fbq) return true\n \n // Verificar se é a versão offline (bloqueada)\n return (window.fbq as any).version === \"2.0-offline\"\n}\n\n// Função para obter estatísticas de bloqueio\nexport function getPixelBlockingStats(): {\n isBlocked: boolean;\n method: string;\n fallbackActive: boolean;\n} {\n return {\n isBlocked: isPixelBlocked(),\n method: window._fbPixelScriptLoaded ? 'script_loaded' : 'script_blocked',\n fallbackActive: !window._fbPixelScriptLoaded && !!window.fbq\n }\n} ","export default {}",";(function (root, factory) {\n\tif (typeof exports === \"object\") {\n\t\t// CommonJS\n\t\tmodule.exports = exports = factory();\n\t}\n\telse if (typeof define === \"function\" && define.amd) {\n\t\t// AMD\n\t\tdefine([], factory);\n\t}\n\telse {\n\t\t// Global (browser)\n\t\troot.CryptoJS = factory();\n\t}\n}(this, function () {\n\n\t/*globals window, global, require*/\n\n\t/**\n\t * CryptoJS core components.\n\t */\n\tvar CryptoJS = CryptoJS || (function (Math, undefined) {\n\n\t var crypto;\n\n\t // Native crypto from window (Browser)\n\t if (typeof window !== 'undefined' && window.crypto) {\n\t crypto = window.crypto;\n\t }\n\n\t // Native crypto in web worker (Browser)\n\t if (typeof self !== 'undefined' && self.crypto) {\n\t crypto = self.crypto;\n\t }\n\n\t // Native crypto from worker\n\t if (typeof globalThis !== 'undefined' && globalThis.crypto) {\n\t crypto = globalThis.crypto;\n\t }\n\n\t // Native (experimental IE 11) crypto from window (Browser)\n\t if (!crypto && typeof window !== 'undefined' && window.msCrypto) {\n\t crypto = window.msCrypto;\n\t }\n\n\t // Native crypto from global (NodeJS)\n\t if (!crypto && typeof global !== 'undefined' && global.crypto) {\n\t crypto = global.crypto;\n\t }\n\n\t // Native crypto import via require (NodeJS)\n\t if (!crypto && typeof require === 'function') {\n\t try {\n\t crypto = require('crypto');\n\t } catch (err) {}\n\t }\n\n\t /*\n\t * Cryptographically secure pseudorandom number generator\n\t *\n\t * As Math.random() is cryptographically not safe to use\n\t */\n\t var cryptoSecureRandomInt = function () {\n\t if (crypto) {\n\t // Use getRandomValues method (Browser)\n\t if (typeof crypto.getRandomValues === 'function') {\n\t try {\n\t return crypto.getRandomValues(new Uint32Array(1))[0];\n\t } catch (err) {}\n\t }\n\n\t // Use randomBytes method (NodeJS)\n\t if (typeof crypto.randomBytes === 'function') {\n\t try {\n\t return crypto.randomBytes(4).readInt32LE();\n\t } catch (err) {}\n\t }\n\t }\n\n\t throw new Error('Native crypto module could not be used to get secure random number.');\n\t };\n\n\t /*\n\t * Local polyfill of Object.create\n\n\t */\n\t var create = Object.create || (function () {\n\t function F() {}\n\n\t return function (obj) {\n\t var subtype;\n\n\t F.prototype = obj;\n\n\t subtype = new F();\n\n\t F.prototype = null;\n\n\t return subtype;\n\t };\n\t }());\n\n\t /**\n\t * CryptoJS namespace.\n\t */\n\t var C = {};\n\n\t /**\n\t * Library namespace.\n\t */\n\t var C_lib = C.lib = {};\n\n\t /**\n\t * Base object for prototypal inheritance.\n\t */\n\t var Base = C_lib.Base = (function () {\n\n\n\t return {\n\t /**\n\t * Creates a new object that inherits from this object.\n\t *\n\t * @param {Object} overrides Properties to copy into the new object.\n\t *\n\t * @return {Object} The new object.\n\t *\n\t * @static\n\t *\n\t * @example\n\t *\n\t * var MyType = CryptoJS.lib.Base.extend({\n\t * field: 'value',\n\t *\n\t * method: function () {\n\t * }\n\t * });\n\t */\n\t extend: function (overrides) {\n\t // Spawn\n\t var subtype = create(this);\n\n\t // Augment\n\t if (overrides) {\n\t subtype.mixIn(overrides);\n\t }\n\n\t // Create default initializer\n\t if (!subtype.hasOwnProperty('init') || this.init === subtype.init) {\n\t subtype.init = function () {\n\t subtype.$super.init.apply(this, arguments);\n\t };\n\t }\n\n\t // Initializer's prototype is the subtype object\n\t subtype.init.prototype = subtype;\n\n\t // Reference supertype\n\t subtype.$super = this;\n\n\t return subtype;\n\t },\n\n\t /**\n\t * Extends this object and runs the init method.\n\t * Arguments to create() will be passed to init().\n\t *\n\t * @return {Object} The new object.\n\t *\n\t * @static\n\t *\n\t * @example\n\t *\n\t * var instance = MyType.create();\n\t */\n\t create: function () {\n\t var instance = this.extend();\n\t instance.init.apply(instance, arguments);\n\n\t return instance;\n\t },\n\n\t /**\n\t * Initializes a newly created object.\n\t * Override this method to add some logic when your objects are created.\n\t *\n\t * @example\n\t *\n\t * var MyType = CryptoJS.lib.Base.extend({\n\t * init: function () {\n\t * // ...\n\t * }\n\t * });\n\t */\n\t init: function () {\n\t },\n\n\t /**\n\t * Copies properties into this object.\n\t *\n\t * @param {Object} properties The properties to mix in.\n\t *\n\t * @example\n\t *\n\t * MyType.mixIn({\n\t * field: 'value'\n\t * });\n\t */\n\t mixIn: function (properties) {\n\t for (var propertyName in properties) {\n\t if (properties.hasOwnProperty(propertyName)) {\n\t this[propertyName] = properties[propertyName];\n\t }\n\t }\n\n\t // IE won't copy toString using the loop above\n\t if (properties.hasOwnProperty('toString')) {\n\t this.toString = properties.toString;\n\t }\n\t },\n\n\t /**\n\t * Creates a copy of this object.\n\t *\n\t * @return {Object} The clone.\n\t *\n\t * @example\n\t *\n\t * var clone = instance.clone();\n\t */\n\t clone: function () {\n\t return this.init.prototype.extend(this);\n\t }\n\t };\n\t }());\n\n\t /**\n\t * An array of 32-bit words.\n\t *\n\t * @property {Array} words The array of 32-bit words.\n\t * @property {number} sigBytes The number of significant bytes in this word array.\n\t */\n\t var WordArray = C_lib.WordArray = Base.extend({\n\t /**\n\t * Initializes a newly created word array.\n\t *\n\t * @param {Array} words (Optional) An array of 32-bit words.\n\t * @param {number} sigBytes (Optional) The number of significant bytes in the words.\n\t *\n\t * @example\n\t *\n\t * var wordArray = CryptoJS.lib.WordArray.create();\n\t * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]);\n\t * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6);\n\t */\n\t init: function (words, sigBytes) {\n\t words = this.words = words || [];\n\n\t if (sigBytes != undefined) {\n\t this.sigBytes = sigBytes;\n\t } else {\n\t this.sigBytes = words.length * 4;\n\t }\n\t },\n\n\t /**\n\t * Converts this word array to a string.\n\t *\n\t * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex\n\t *\n\t * @return {string} The stringified word array.\n\t *\n\t * @example\n\t *\n\t * var string = wordArray + '';\n\t * var string = wordArray.toString();\n\t * var string = wordArray.toString(CryptoJS.enc.Utf8);\n\t */\n\t toString: function (encoder) {\n\t return (encoder || Hex).stringify(this);\n\t },\n\n\t /**\n\t * Concatenates a word array to this word array.\n\t *\n\t * @param {WordArray} wordArray The word array to append.\n\t *\n\t * @return {WordArray} This word array.\n\t *\n\t * @example\n\t *\n\t * wordArray1.concat(wordArray2);\n\t */\n\t concat: function (wordArray) {\n\t // Shortcuts\n\t var thisWords = this.words;\n\t var thatWords = wordArray.words;\n\t var thisSigBytes = this.sigBytes;\n\t var thatSigBytes = wordArray.sigBytes;\n\n\t // Clamp excess bits\n\t this.clamp();\n\n\t // Concat\n\t if (thisSigBytes % 4) {\n\t // Copy one byte at a time\n\t for (var i = 0; i < thatSigBytes; i++) {\n\t var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;\n\t thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8);\n\t }\n\t } else {\n\t // Copy one word at a time\n\t for (var j = 0; j < thatSigBytes; j += 4) {\n\t thisWords[(thisSigBytes + j) >>> 2] = thatWords[j >>> 2];\n\t }\n\t }\n\t this.sigBytes += thatSigBytes;\n\n\t // Chainable\n\t return this;\n\t },\n\n\t /**\n\t * Removes insignificant bits.\n\t *\n\t * @example\n\t *\n\t * wordArray.clamp();\n\t */\n\t clamp: function () {\n\t // Shortcuts\n\t var words = this.words;\n\t var sigBytes = this.sigBytes;\n\n\t // Clamp\n\t words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8);\n\t words.length = Math.ceil(sigBytes / 4);\n\t },\n\n\t /**\n\t * Creates a copy of this word array.\n\t *\n\t * @return {WordArray} The clone.\n\t *\n\t * @example\n\t *\n\t * var clone = wordArray.clone();\n\t */\n\t clone: function () {\n\t var clone = Base.clone.call(this);\n\t clone.words = this.words.slice(0);\n\n\t return clone;\n\t },\n\n\t /**\n\t * Creates a word array filled with random bytes.\n\t *\n\t * @param {number} nBytes The number of random bytes to generate.\n\t *\n\t * @return {WordArray} The random word array.\n\t *\n\t * @static\n\t *\n\t * @example\n\t *\n\t * var wordArray = CryptoJS.lib.WordArray.random(16);\n\t */\n\t random: function (nBytes) {\n\t var words = [];\n\n\t for (var i = 0; i < nBytes; i += 4) {\n\t words.push(cryptoSecureRandomInt());\n\t }\n\n\t return new WordArray.init(words, nBytes);\n\t }\n\t });\n\n\t /**\n\t * Encoder namespace.\n\t */\n\t var C_enc = C.enc = {};\n\n\t /**\n\t * Hex encoding strategy.\n\t */\n\t var Hex = C_enc.Hex = {\n\t /**\n\t * Converts a word array to a hex string.\n\t *\n\t * @param {WordArray} wordArray The word array.\n\t *\n\t * @return {string} The hex string.\n\t *\n\t * @static\n\t *\n\t * @example\n\t *\n\t * var hexString = CryptoJS.enc.Hex.stringify(wordArray);\n\t */\n\t stringify: function (wordArray) {\n\t // Shortcuts\n\t var words = wordArray.words;\n\t var sigBytes = wordArray.sigBytes;\n\n\t // Convert\n\t var hexChars = [];\n\t for (var i = 0; i < sigBytes; i++) {\n\t var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;\n\t hexChars.push((bite >>> 4).toString(16));\n\t hexChars.push((bite & 0x0f).toString(16));\n\t }\n\n\t return hexChars.join('');\n\t },\n\n\t /**\n\t * Converts a hex string to a word array.\n\t *\n\t * @param {string} hexStr The hex string.\n\t *\n\t * @return {WordArray} The word array.\n\t *\n\t * @static\n\t *\n\t * @example\n\t *\n\t * var wordArray = CryptoJS.enc.Hex.parse(hexString);\n\t */\n\t parse: function (hexStr) {\n\t // Shortcut\n\t var hexStrLength = hexStr.length;\n\n\t // Convert\n\t var words = [];\n\t for (var i = 0; i < hexStrLength; i += 2) {\n\t words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4);\n\t }\n\n\t return new WordArray.init(words, hexStrLength / 2);\n\t }\n\t };\n\n\t /**\n\t * Latin1 encoding strategy.\n\t */\n\t var Latin1 = C_enc.Latin1 = {\n\t /**\n\t * Converts a word array to a Latin1 string.\n\t *\n\t * @param {WordArray} wordArray The word array.\n\t *\n\t * @return {string} The Latin1 string.\n\t *\n\t * @static\n\t *\n\t * @example\n\t *\n\t * var latin1String = CryptoJS.enc.Latin1.stringify(wordArray);\n\t */\n\t stringify: function (wordArray) {\n\t // Shortcuts\n\t var words = wordArray.words;\n\t var sigBytes = wordArray.sigBytes;\n\n\t // Convert\n\t var latin1Chars = [];\n\t for (var i = 0; i < sigBytes; i++) {\n\t var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;\n\t latin1Chars.push(String.fromCharCode(bite));\n\t }\n\n\t return latin1Chars.join('');\n\t },\n\n\t /**\n\t * Converts a Latin1 string to a word array.\n\t *\n\t * @param {string} latin1Str The Latin1 string.\n\t *\n\t * @return {WordArray} The word array.\n\t *\n\t * @static\n\t *\n\t * @example\n\t *\n\t * var wordArray = CryptoJS.enc.Latin1.parse(latin1String);\n\t */\n\t parse: function (latin1Str) {\n\t // Shortcut\n\t var latin1StrLength = latin1Str.length;\n\n\t // Convert\n\t var words = [];\n\t for (var i = 0; i < latin1StrLength; i++) {\n\t words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8);\n\t }\n\n\t return new WordArray.init(words, latin1StrLength);\n\t }\n\t };\n\n\t /**\n\t * UTF-8 encoding strategy.\n\t */\n\t var Utf8 = C_enc.Utf8 = {\n\t /**\n\t * Converts a word array to a UTF-8 string.\n\t *\n\t * @param {WordArray} wordArray The word array.\n\t *\n\t * @return {string} The UTF-8 string.\n\t *\n\t * @static\n\t *\n\t * @example\n\t *\n\t * var utf8String = CryptoJS.enc.Utf8.stringify(wordArray);\n\t */\n\t stringify: function (wordArray) {\n\t try {\n\t return decodeURIComponent(escape(Latin1.stringify(wordArray)));\n\t } catch (e) {\n\t throw new Error('Malformed UTF-8 data');\n\t }\n\t },\n\n\t /**\n\t * Converts a UTF-8 string to a word array.\n\t *\n\t * @param {string} utf8Str The UTF-8 string.\n\t *\n\t * @return {WordArray} The word array.\n\t *\n\t * @static\n\t *\n\t * @example\n\t *\n\t * var wordArray = CryptoJS.enc.Utf8.parse(utf8String);\n\t */\n\t parse: function (utf8Str) {\n\t return Latin1.parse(unescape(encodeURIComponent(utf8Str)));\n\t }\n\t };\n\n\t /**\n\t * Abstract buffered block algorithm template.\n\t *\n\t * The property blockSize must be implemented in a concrete subtype.\n\t *\n\t * @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0\n\t */\n\t var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({\n\t /**\n\t * Resets this block algorithm's data buffer to its initial state.\n\t *\n\t * @example\n\t *\n\t * bufferedBlockAlgorithm.reset();\n\t */\n\t reset: function () {\n\t // Initial values\n\t this._data = new WordArray.init();\n\t this._nDataBytes = 0;\n\t },\n\n\t /**\n\t * Adds new data to this block algorithm's buffer.\n\t *\n\t * @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8.\n\t *\n\t * @example\n\t *\n\t * bufferedBlockAlgorithm._append('data');\n\t * bufferedBlockAlgorithm._append(wordArray);\n\t */\n\t _append: function (data) {\n\t // Convert string to WordArray, else assume WordArray already\n\t if (typeof data == 'string') {\n\t data = Utf8.parse(data);\n\t }\n\n\t // Append\n\t this._data.concat(data);\n\t this._nDataBytes += data.sigBytes;\n\t },\n\n\t /**\n\t * Processes available data blocks.\n\t *\n\t * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype.\n\t *\n\t * @param {boolean} doFlush Whether all blocks and partial blocks should be processed.\n\t *\n\t * @return {WordArray} The processed data.\n\t *\n\t * @example\n\t *\n\t * var processedData = bufferedBlockAlgorithm._process();\n\t * var processedData = bufferedBlockAlgorithm._process(!!'flush');\n\t */\n\t _process: function (doFlush) {\n\t var processedWords;\n\n\t // Shortcuts\n\t var data = this._data;\n\t var dataWords = data.words;\n\t var dataSigBytes = data.sigBytes;\n\t var blockSize = this.blockSize;\n\t var blockSizeBytes = blockSize * 4;\n\n\t // Count blocks ready\n\t var nBlocksReady = dataSigBytes / blockSizeBytes;\n\t if (doFlush) {\n\t // Round up to include partial blocks\n\t nBlocksReady = Math.ceil(nBlocksReady);\n\t } else {\n\t // Round down to include only full blocks,\n\t // less the number of blocks that must remain in the buffer\n\t nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0);\n\t }\n\n\t // Count words ready\n\t var nWordsReady = nBlocksReady * blockSize;\n\n\t // Count bytes ready\n\t var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes);\n\n\t // Process blocks\n\t if (nWordsReady) {\n\t for (var offset = 0; offset < nWordsReady; offset += blockSize) {\n\t // Perform concrete-algorithm logic\n\t this._doProcessBlock(dataWords, offset);\n\t }\n\n\t // Remove processed words\n\t processedWords = dataWords.splice(0, nWordsReady);\n\t data.sigBytes -= nBytesReady;\n\t }\n\n\t // Return processed words\n\t return new WordArray.init(processedWords, nBytesReady);\n\t },\n\n\t /**\n\t * Creates a copy of this object.\n\t *\n\t * @return {Object} The clone.\n\t *\n\t * @example\n\t *\n\t * var clone = bufferedBlockAlgorithm.clone();\n\t */\n\t clone: function () {\n\t var clone = Base.clone.call(this);\n\t clone._data = this._data.clone();\n\n\t return clone;\n\t },\n\n\t _minBufferSize: 0\n\t });\n\n\t /**\n\t * Abstract hasher template.\n\t *\n\t * @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits)\n\t */\n\t var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({\n\t /**\n\t * Configuration options.\n\t */\n\t cfg: Base.extend(),\n\n\t /**\n\t * Initializes a newly created hasher.\n\t *\n\t * @param {Object} cfg (Optional) The configuration options to use for this hash computation.\n\t *\n\t * @example\n\t *\n\t * var hasher = CryptoJS.algo.SHA256.create();\n\t */\n\t init: function (cfg) {\n\t // Apply config defaults\n\t this.cfg = this.cfg.extend(cfg);\n\n\t // Set initial values\n\t this.reset();\n\t },\n\n\t /**\n\t * Resets this hasher to its initial state.\n\t *\n\t * @example\n\t *\n\t * hasher.reset();\n\t */\n\t reset: function () {\n\t // Reset data buffer\n\t BufferedBlockAlgorithm.reset.call(this);\n\n\t // Perform concrete-hasher logic\n\t this._doReset();\n\t },\n\n\t /**\n\t * Updates this hasher with a message.\n\t *\n\t * @param {WordArray|string} messageUpdate The message to append.\n\t *\n\t * @return {Hasher} This hasher.\n\t *\n\t * @example\n\t *\n\t * hasher.update('message');\n\t * hasher.update(wordArray);\n\t */\n\t update: function (messageUpdate) {\n\t // Append\n\t this._append(messageUpdate);\n\n\t // Update the hash\n\t this._process();\n\n\t // Chainable\n\t return this;\n\t },\n\n\t /**\n\t * Finalizes the hash computation.\n\t * Note that the finalize operation is effectively a destructive, read-once operation.\n\t *\n\t * @param {WordArray|string} messageUpdate (Optional) A final message update.\n\t *\n\t * @return {WordArray} The hash.\n\t *\n\t * @example\n\t *\n\t * var hash = hasher.finalize();\n\t * var hash = hasher.finalize('message');\n\t * var hash = hasher.finalize(wordArray);\n\t */\n\t finalize: function (messageUpdate) {\n\t // Final message update\n\t if (messageUpdate) {\n\t this._append(messageUpdate);\n\t }\n\n\t // Perform concrete-hasher logic\n\t var hash = this._doFinalize();\n\n\t return hash;\n\t },\n\n\t blockSize: 512/32,\n\n\t /**\n\t * Creates a shortcut function to a hasher's object interface.\n\t *\n\t * @param {Hasher} hasher The hasher to create a helper for.\n\t *\n\t * @return {Function} The shortcut function.\n\t *\n\t * @static\n\t *\n\t * @example\n\t *\n\t * var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256);\n\t */\n\t _createHelper: function (hasher) {\n\t return function (message, cfg) {\n\t return new hasher.init(cfg).finalize(message);\n\t };\n\t },\n\n\t /**\n\t * Creates a shortcut function to the HMAC's object interface.\n\t *\n\t * @param {Hasher} hasher The hasher to use in this HMAC helper.\n\t *\n\t * @return {Function} The shortcut function.\n\t *\n\t * @static\n\t *\n\t * @example\n\t *\n\t * var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256);\n\t */\n\t _createHmacHelper: function (hasher) {\n\t return function (message, key) {\n\t return new C_algo.HMAC.init(hasher, key).finalize(message);\n\t };\n\t }\n\t });\n\n\t /**\n\t * Algorithm namespace.\n\t */\n\t var C_algo = C.algo = {};\n\n\t return C;\n\t}(Math));\n\n\n\treturn CryptoJS;\n\n}));",";(function (root, factory) {\n\tif (typeof exports === \"object\") {\n\t\t// CommonJS\n\t\tmodule.exports = exports = factory(require(\"./core\"));\n\t}\n\telse if (typeof define === \"function\" && define.amd) {\n\t\t// AMD\n\t\tdefine([\"./core\"], factory);\n\t}\n\telse {\n\t\t// Global (browser)\n\t\tfactory(root.CryptoJS);\n\t}\n}(this, function (CryptoJS) {\n\n\t(function (Math) {\n\t // Shortcuts\n\t var C = CryptoJS;\n\t var C_lib = C.lib;\n\t var WordArray = C_lib.WordArray;\n\t var Hasher = C_lib.Hasher;\n\t var C_algo = C.algo;\n\n\t // Initialization and round constants tables\n\t var H = [];\n\t var K = [];\n\n\t // Compute constants\n\t (function () {\n\t function isPrime(n) {\n\t var sqrtN = Math.sqrt(n);\n\t for (var factor = 2; factor <= sqr