mirror of
https://github.com/lucasrcsantana/story-generator.git
synced 2025-12-17 05:47:52 +00:00
Implementação do GTM
This commit is contained in:
parent
75d9d4635b
commit
1542572be4
39
src/components/analytics/GoogleTagManager.tsx
Normal file
39
src/components/analytics/GoogleTagManager.tsx
Normal file
@ -0,0 +1,39 @@
|
||||
import React from 'react';
|
||||
|
||||
interface GoogleTagManagerProps {
|
||||
gtmId: string;
|
||||
}
|
||||
|
||||
export function GoogleTagManager({ gtmId }: GoogleTagManagerProps) {
|
||||
React.useEffect(() => {
|
||||
// Carrega o script do GTM
|
||||
const script = document.createElement('script');
|
||||
script.innerHTML = `
|
||||
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
|
||||
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
|
||||
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
|
||||
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
|
||||
})(window,document,'script','dataLayer','${gtmId}');
|
||||
`;
|
||||
document.head.appendChild(script);
|
||||
|
||||
// Adiciona o noscript iframe
|
||||
const noscript = document.createElement('noscript');
|
||||
const iframe = document.createElement('iframe');
|
||||
iframe.src = `https://www.googletagmanager.com/ns.html?id=${gtmId}`;
|
||||
iframe.height = '0';
|
||||
iframe.width = '0';
|
||||
iframe.style.display = 'none';
|
||||
iframe.style.visibility = 'hidden';
|
||||
noscript.appendChild(iframe);
|
||||
document.body.insertBefore(noscript, document.body.firstChild);
|
||||
|
||||
return () => {
|
||||
// Cleanup
|
||||
document.head.removeChild(script);
|
||||
document.body.removeChild(noscript);
|
||||
};
|
||||
}, [gtmId]);
|
||||
|
||||
return null;
|
||||
}
|
||||
@ -3,6 +3,7 @@ import { LogIn, Eye, EyeOff, School, GraduationCap, User } from 'lucide-react';
|
||||
import { useAuth } from '../../hooks/useAuth';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { supabase } from '../../lib/supabase';
|
||||
import { useDataLayer } from '../../hooks/useDataLayer';
|
||||
|
||||
interface LoginFormProps {
|
||||
userType: 'school' | 'teacher' | 'student';
|
||||
@ -30,6 +31,7 @@ export function LoginForm({ userType, onLogin, onRegisterClick }: LoginFormProps
|
||||
const [loading, setLoading] = useState(false);
|
||||
const { signIn } = useAuth();
|
||||
const navigate = useNavigate();
|
||||
const { trackEvent } = useDataLayer();
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
@ -75,6 +77,7 @@ export function LoginForm({ userType, onLogin, onRegisterClick }: LoginFormProps
|
||||
throw new Error('Tipo de usuário inválido');
|
||||
}
|
||||
|
||||
trackEvent('auth', 'login_success', 'form');
|
||||
} catch (err) {
|
||||
console.error('Erro no login:', err);
|
||||
if (err instanceof Error) {
|
||||
@ -82,6 +85,7 @@ export function LoginForm({ userType, onLogin, onRegisterClick }: LoginFormProps
|
||||
} else {
|
||||
setError('Email ou senha incorretos');
|
||||
}
|
||||
trackEvent('auth', 'login_error', err.message);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
60
src/hooks/useDataLayer.ts
Normal file
60
src/hooks/useDataLayer.ts
Normal file
@ -0,0 +1,60 @@
|
||||
interface DataLayerEvent {
|
||||
event: string;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
dataLayer: any[];
|
||||
}
|
||||
}
|
||||
|
||||
export function useDataLayer() {
|
||||
// Inicializa o dataLayer se não existir
|
||||
if (!window.dataLayer) {
|
||||
window.dataLayer = [];
|
||||
}
|
||||
|
||||
const push = (data: DataLayerEvent) => {
|
||||
window.dataLayer.push(data);
|
||||
};
|
||||
|
||||
const pageView = (path: string) => {
|
||||
push({
|
||||
event: 'pageview',
|
||||
page: {
|
||||
path,
|
||||
title: document.title,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const trackEvent = (
|
||||
category: string,
|
||||
action: string,
|
||||
label?: string,
|
||||
value?: number
|
||||
) => {
|
||||
push({
|
||||
event: 'track_event',
|
||||
category,
|
||||
action,
|
||||
label,
|
||||
value,
|
||||
});
|
||||
};
|
||||
|
||||
const trackUserProperties = (properties: Record<string, any>) => {
|
||||
push({
|
||||
event: 'set_user_properties',
|
||||
user_properties: properties,
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
push,
|
||||
pageView,
|
||||
trackEvent,
|
||||
trackUserProperties,
|
||||
};
|
||||
}
|
||||
@ -5,8 +5,12 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
import * as Sentry from "@sentry/react";
|
||||
import { router } from './routes';
|
||||
import { Toaster } from './components/ui/toaster';
|
||||
import { GoogleTagManager } from './components/analytics/GoogleTagManager';
|
||||
import './index.css';
|
||||
|
||||
// GTM ID - Substitua pelo seu ID real do GTM
|
||||
const GTM_ID = import.meta.env.VITE_GTM_ID;
|
||||
|
||||
// Inicialização do Sentry
|
||||
Sentry.init({
|
||||
dsn: "https://6c15876055bf4a860c1b63a8e4e7ca65@o544400.ingest.us.sentry.io/4508626073092096",
|
||||
@ -49,6 +53,7 @@ const queryClient = new QueryClient({
|
||||
function Root() {
|
||||
return (
|
||||
<StrictMode>
|
||||
<GoogleTagManager gtmId={GTM_ID} />
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<RouterProvider router={router} />
|
||||
<Toaster />
|
||||
|
||||
Loading…
Reference in New Issue
Block a user