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:
1 parent
54d99fbffd
commit
525ef140fe
5 files changed
+40
-195
No files matched your search
@@ -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 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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
@@ -3,6 +3,7 @@ import { Geist, Geist_Mono } from "next/font/google";
|
|||||||
import Script from "next/script";
|
import Script from "next/script";
|
||||||
// Importação necessária para corrigir o erro de namespace e tipagem do children
|
// Importação necessária para corrigir o erro de namespace e tipagem do children
|
||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
|
import GoogleAnalytics from "./components/GoogleAnalytics";
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
|
|
||||||
const geistSans = Geist({
|
const geistSans = Geist({
|
||||||
@@ -194,85 +195,7 @@ export default function RootLayout({ children }: Readonly<RootLayoutProps>) {
|
|||||||
data-session-replay="true"
|
data-session-replay="true"
|
||||||
data-track-errors="true"
|
data-track-errors="true"
|
||||||
/>
|
/>
|
||||||
{/* Google Analytics - Interceptor para bypass de adblocker */}
|
<GoogleAnalytics />
|
||||||
<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'
|
|
||||||
});
|
|
||||||
`,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
|
|||||||
+8
-4
@@ -79,11 +79,15 @@ const nextConfig: NextConfig = {
|
|||||||
source: "/analytics/:match*",
|
source: "/analytics/:match*",
|
||||||
destination: "https://analytics.evandro.dev.br/:match*",
|
destination: "https://analytics.evandro.dev.br/:match*",
|
||||||
},
|
},
|
||||||
// Google Analytics - Fallback rewrites (as API routes são preferenciais)
|
// Google Analytics - Script principal
|
||||||
// Estes rewrites servem como fallback caso as API routes falhem
|
|
||||||
{
|
{
|
||||||
source: "/api/gtm/:id",
|
source: "/metrics/js/script.js",
|
||||||
destination: "https://www.googletagmanager.com/gtag/js?id=:id",
|
destination: "https://www.googletagmanager.com/gtag/js?id=G-QTT9QT0T3S",
|
||||||
|
},
|
||||||
|
// Google Analytics - Endpoint de coleta
|
||||||
|
{
|
||||||
|
source: "/metrics/collect",
|
||||||
|
destination: "https://www.google-analytics.com/g/collect",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in new issue
Block a user