From 6a1a471ce56366c82ce4559e0f592b809a13a24e Mon Sep 17 00:00:00 2001 From: Lucas Santana Date: Fri, 17 Jan 2025 12:51:36 -0300 Subject: [PATCH] =?UTF-8?q?fix:=20Corrigindo=20deduplica=C3=A7=C3=A3o=20de?= =?UTF-8?q?=20eventos=20no=20Rudderstack?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/analytics/PageTracker.tsx | 161 +++++++++++++---------- src/routes.tsx | 2 - 2 files changed, 93 insertions(+), 70 deletions(-) diff --git a/src/components/analytics/PageTracker.tsx b/src/components/analytics/PageTracker.tsx index e1ead57..9403b61 100644 --- a/src/components/analytics/PageTracker.tsx +++ b/src/components/analytics/PageTracker.tsx @@ -1,4 +1,4 @@ -import { useEffect } from 'react'; +import { useEffect, useRef } from 'react'; import { useRudderstack } from '../../hooks/useRudderstack'; import { useLocation } from 'react-router-dom'; import { useAuth } from '../../hooks/useAuth'; @@ -7,81 +7,106 @@ export function PageTracker() { const location = useLocation(); const { page } = useRudderstack(); const { user } = useAuth(); + const lastPageTracked = useRef(null); + const timeoutRef = useRef(); useEffect(() => { - // Coleta informações do dispositivo/navegador - const deviceInfo = { - screenWidth: window.screen.width, - screenHeight: window.screen.height, - viewportWidth: window.innerWidth, - viewportHeight: window.innerHeight, - deviceType: getDeviceType(), - deviceOrientation: window.screen.orientation.type, - userAgent: navigator.userAgent, - language: navigator.language, - }; + // Se já rastreamos esta página, não rastrear novamente + if (lastPageTracked.current === location.pathname) { + return; + } - // Coleta informações de performance - const performanceInfo = { - loadTime: window.performance.timing.loadEventEnd - window.performance.timing.navigationStart, - domInteractive: window.performance.timing.domInteractive - window.performance.timing.navigationStart, - firstContentfulPaint: getFirstContentfulPaint(), - }; + // Limpa o timeout anterior se existir + if (timeoutRef.current) { + clearTimeout(timeoutRef.current); + } - // Informações da sessão - const sessionInfo = { - sessionStartTime: sessionStorage.getItem('sessionStartTime') || new Date().toISOString(), - isFirstVisit: !localStorage.getItem('returningVisitor'), - lastVisitedPage: sessionStorage.getItem('lastVisitedPage'), - }; + // Debounce de 300ms para evitar múltiplos eventos + timeoutRef.current = setTimeout(() => { + // Coleta informações do dispositivo/navegador + const deviceInfo = { + screenWidth: window.screen.width, + screenHeight: window.screen.height, + viewportWidth: window.innerWidth, + viewportHeight: window.innerHeight, + deviceType: getDeviceType(), + deviceOrientation: window.screen.orientation.type, + userAgent: navigator.userAgent, + language: navigator.language, + }; - // Traits do usuário (se autenticado) - const userTraits = user ? { - user_id: user.id, - email: user.email, - school_id: user.user_metadata?.school_id, - class_id: user.user_metadata?.class_id, - name: user.user_metadata?.name, - role: user.user_metadata?.role, - last_updated: user.updated_at, - created_at: user.created_at - } : {}; + // Coleta informações de performance + const performanceInfo = { + loadTime: window.performance.timing.loadEventEnd - window.performance.timing.navigationStart, + domInteractive: window.performance.timing.domInteractive - window.performance.timing.navigationStart, + firstContentfulPaint: getFirstContentfulPaint(), + }; - // Envia dados adicionais usando o page() do Rudderstack - page(undefined, { - // Informações da página - path: location.pathname, - search: location.search, - hash: location.hash, - title: document.title, - referrer: document.referrer, - url: window.location.href, - - // Informações do dispositivo e navegador - ...deviceInfo, - - // Informações de performance - ...performanceInfo, - // Informações da sessão - ...sessionInfo, - - // Traits do usuário - ...userTraits, - - // Metadados adicionais - timezone: Intl.DateTimeFormat().resolvedOptions().timeZone, - }); + const sessionInfo = { + sessionStartTime: sessionStorage.getItem('sessionStartTime') || new Date().toISOString(), + isFirstVisit: !localStorage.getItem('returningVisitor'), + lastVisitedPage: sessionStorage.getItem('lastVisitedPage'), + }; - // Atualiza informações da sessão - sessionStorage.setItem('lastVisitedPage', location.pathname); - if (!localStorage.getItem('returningVisitor')) { - localStorage.setItem('returningVisitor', 'true'); - } - if (!sessionStorage.getItem('sessionStartTime')) { - sessionStorage.setItem('sessionStartTime', new Date().toISOString()); - } - }, [location, page, user]); + // Traits do usuário (se autenticado) + const userTraits = user ? { + user_id: user.id, + email: user.email, + school_id: user.user_metadata?.school_id, + class_id: user.user_metadata?.class_id, + name: user.user_metadata?.name, + role: user.user_metadata?.role, + last_updated: user.updated_at, + created_at: user.created_at + } : {}; + + // Envia dados adicionais usando o page() do Rudderstack + page(undefined, { + // Informações da página + path: location.pathname, + search: location.search, + hash: location.hash, + title: document.title, + referrer: document.referrer, + url: window.location.href, + + // Informações do dispositivo e navegador + ...deviceInfo, + + // Informações de performance + ...performanceInfo, + + // Informações da sessão + ...sessionInfo, + + // Traits do usuário + ...userTraits, + + // Metadados adicionais + timezone: Intl.DateTimeFormat().resolvedOptions().timeZone, + }); + + // Atualiza a última página rastreada + lastPageTracked.current = location.pathname; + + // Atualiza informações da sessão + sessionStorage.setItem('lastVisitedPage', location.pathname); + if (!localStorage.getItem('returningVisitor')) { + localStorage.setItem('returningVisitor', 'true'); + } + if (!sessionStorage.getItem('sessionStartTime')) { + sessionStorage.setItem('sessionStartTime', new Date().toISOString()); + } + }, 300); + + // Cleanup + return () => { + if (timeoutRef.current) { + clearTimeout(timeoutRef.current); + } + }; + }, [location.pathname, user]); // Reduzido dependências para apenas pathname e user return null; } diff --git a/src/routes.tsx b/src/routes.tsx index 0a89eea..c7a5fdf 100644 --- a/src/routes.tsx +++ b/src/routes.tsx @@ -33,12 +33,10 @@ import { TestWordHighlighter } from './pages/TestWordHighlighter'; import { ExercisePage } from './pages/student-dashboard/ExercisePage'; import { EvidenceBased } from './pages/landing/EvidenceBased'; import { TextSalesLetter } from './pages/landing/TextSalesLetter'; -import { PageTracker } from './components/analytics/PageTracker'; function RootLayout({ children }: { children: React.ReactNode }) { return ( <> - {children} );