refactor(analytics): streamline Google Analytics integration and remove proxy routes

- Replaced the previous Google Analytics proxy routes with a direct integration in the layout component for improved performance and simplicity.
- Updated the Next.js configuration to include new rewrite rules for Google Analytics scripts and collection endpoints.
- Removed outdated proxy logic to enhance code clarity and maintainability.
This commit is contained in:
Evandro Fonseca Junior committed 2026-01-20 21:20:03 -03:00
1 parent 54d99fbffd
commit 525ef140fe
5 files changed
+40 -195

No files matched your search

-47
View File
@@ -1,47 +0,0 @@
import { NextRequest, NextResponse } from 'next/server';
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
const { id } = await params;
try {
const response = await fetch(
`https://www.googletagmanager.com/gtag/js?id=${id}`,
{
headers: {
'User-Agent': request.headers.get('user-agent') || '',
},
}
);
if (!response.ok) {
return new NextResponse('Script not found', { status: 404 });
}
const scriptContent = await response.text();
// Modificar URLs internas do script para usar o proxy
const modifiedScript = scriptContent
.replace(
/https?:\/\/[^\/]*google-analytics\.com\/g\/collect/g,
'/api/metrics'
)
.replace(
/https?:\/\/[^\/]*google-analytics\.com/g,
'/api/metrics'
);
return new NextResponse(modifiedScript, {
status: 200,
headers: {
'Content-Type': 'application/javascript',
'Cache-Control': 'public, max-age=3600',
},
});
} catch (error) {
console.error('GTM proxy error:', error);
return new NextResponse('Proxy error', { status: 500 });
}
}
-65
View File
@@ -1,65 +0,0 @@
import { NextRequest, NextResponse } from 'next/server';
export async function GET(request: NextRequest) {
const searchParams = request.nextUrl.searchParams;
const url = new URL('https://www.google-analytics.com/g/collect');
// Copiar todos os parâmetros da query string
searchParams.forEach((value, key) => {
url.searchParams.append(key, value);
});
try {
const response = await fetch(url.toString(), {
method: 'GET',
headers: {
'User-Agent': request.headers.get('user-agent') || '',
'Accept-Language': request.headers.get('accept-language') || '',
},
});
return new NextResponse(null, {
status: response.status,
headers: {
'Cache-Control': 'no-cache, no-store, must-revalidate',
},
});
} catch (error) {
console.error('Google Analytics proxy error:', error);
return new NextResponse(null, { status: 200 }); // Retornar 200 para não quebrar o tracking
}
}
export async function POST(request: NextRequest) {
const searchParams = request.nextUrl.searchParams;
const url = new URL('https://www.google-analytics.com/g/collect');
// Copiar todos os parâmetros da query string
searchParams.forEach((value, key) => {
url.searchParams.append(key, value);
});
try {
const body = await request.text();
const response = await fetch(url.toString(), {
method: 'POST',
headers: {
'User-Agent': request.headers.get('user-agent') || '',
'Accept-Language': request.headers.get('accept-language') || '',
'Content-Type': 'text/plain',
},
body: body || undefined,
});
return new NextResponse(null, {
status: response.status,
headers: {
'Cache-Control': 'no-cache, no-store, must-revalidate',
},
});
} catch (error) {
console.error('Google Analytics proxy error:', error);
return new NextResponse(null, { status: 200 });
}
}
+30
View File
@@ -0,0 +1,30 @@
'use client';
import Script from 'next/script';
const GA_MEASUREMENT_ID = 'G-QTT9QT0T3S';
export default function GoogleAnalytics() {
return (
<>
<Script
src="/metrics/js/script.js"
strategy="afterInteractive"
/>
<Script id="google-analytics" strategy="afterInteractive">
{`
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${GA_MEASUREMENT_ID}', {
transport_url: '/metrics/collect',
cookie_flags: 'SameSite=None;Secure',
allow_ad_personalization_signals: false,
anonymize_ip: true
});
`}
</Script>
</>
);
}
+2 -79
View File
@@ -3,6 +3,7 @@ import { Geist, Geist_Mono } from "next/font/google";
import Script from "next/script";
// Importação necessária para corrigir o erro de namespace e tipagem do children
import { ReactNode } from "react";
import GoogleAnalytics from "./components/GoogleAnalytics";
import "./globals.css";
const geistSans = Geist({
@@ -194,85 +195,7 @@ export default function RootLayout({ children }: Readonly<RootLayoutProps>) {
data-session-replay="true"
data-track-errors="true"
/>
{/* Google Analytics - Interceptor para bypass de adblocker */}
<Script
id="google-analytics-proxy-interceptor"
strategy="beforeInteractive"
dangerouslySetInnerHTML={{
__html: `
(function() {
// Interceptar fetch - método mais robusto
const originalFetch = window.fetch;
window.fetch = function(url, options) {
if (typeof url === 'string') {
// Interceptar google-analytics.com/g/collect
if (url.includes('google-analytics.com/g/collect')) {
const urlObj = new URL(url);
url = '/api/metrics' + urlObj.search;
}
// Interceptar outros endpoints do google-analytics.com
else if (url.includes('google-analytics.com')) {
url = url.replace(/https?:\\/\\/[^\\/]*google-analytics\\.com/g, '/api/metrics');
}
}
return originalFetch.call(this, url, options);
};
// Interceptar XMLHttpRequest
const originalOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, url, ...rest) {
if (typeof url === 'string') {
if (url.includes('google-analytics.com/g/collect')) {
const urlObj = new URL(url);
url = '/api/metrics' + urlObj.search;
}
else if (url.includes('google-analytics.com')) {
url = url.replace(/https?:\\/\\/[^\\/]*google-analytics\\.com/g, '/api/metrics');
}
}
return originalOpen.call(this, method, url, ...rest);
};
// Interceptar sendBeacon (método usado pelo GA4)
const originalSendBeacon = navigator.sendBeacon;
navigator.sendBeacon = function(url, data) {
if (typeof url === 'string') {
if (url.includes('google-analytics.com/g/collect')) {
const urlObj = new URL(url);
return originalSendBeacon.call(this, '/api/metrics' + urlObj.search, data);
}
else if (url.includes('google-analytics.com')) {
url = url.replace(/https?:\\/\\/[^\\/]*google-analytics\\.com/g, '/api/metrics');
}
}
return originalSendBeacon.call(this, url, data);
};
})();
`,
}}
/>
{/* Google Analytics - Script principal via proxy */}
<Script
src="/api/gtm/G-QTT9QT0T3S"
strategy="afterInteractive"
async
/>
{/* Google Analytics - Inicialização */}
<Script
id="google-analytics-init"
strategy="afterInteractive"
dangerouslySetInnerHTML={{
__html: `
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-QTT9QT0T3S', {
// Forçar uso de fetch em vez de imagem beacon
transport_type: 'fetch'
});
`,
}}
/>
<GoogleAnalytics />
</body>
</html>
);