Google Analytics Reverse Proxy
How? I feel some inconsistency in my Analytics numbers and some traffic analysis tools. Also, my traffic may be coming from places where there is a possible adblock.
In a Wasp/React TypeScript project, we can implement this by creating a proxy API endpoint and modifying how we load the analytics scripts. Here's how to do it:
- First, create a proxy API endpoint in your Wasp project:
- Create the proxy implementation:
>/api/analytics/${measurementId}`;
- Create a custom Analytics component to load the scripts:
document.head.appendChild(script);
// Initialize gtag>
window.dataLayer = window.dataLayer || [];
function gtag(...args: any[]) {
window.dataLayer.push(args);
}
gtag('js', new Date());
gtag('config', measurementId, { send_page_view: false });
return () => {
// Cleanup
document.head.removeChild(script);
};
}, [measurementId]);
return null;
};```
- Update your App component to use the new Analytics component:
- Add necessary type definitions:
- Update your main.wasp file to remove the direct script tags
// ... existing code ...
api analyticsProxy {
fn: import { analyticsProxy } from "@src/server/analytics/proxy.ts",
httpRoute: (GET, "/api/analytics/:script"),
}
api tagManagerProxy {
fn: import { tagManagerProxy } from "@src/server/analytics/proxy.ts",
httpRoute: (GET, "/api/gtm/:script"),
}import { Request, Response } from 'express';
import axios from 'axios';
const ANALYTICS_URL = 'https://www.googletagmanager.com/gtag/js';
const GTM_URL = 'https://www.googletagmanager.com/gtm.js';
export const analyticsProxy = async (req: Request, res: Response) => {
try {
const response = await axios.get(`${ANALYTICS_URL}?id=${req.params.script}`, {
responseType: 'stream'
});
// Set appropriate headers
res.setHeader('Content-Type', 'application/javascript');
res.setHeader('Cache-Control', 'public, max-age=3600'); // Cache for 1 hour
// Pipe the response
response.data.pipe(res);
} catch (error) {
console.error('Analytics proxy error:', error);
res.status(500).send('Error loading analytics');
}
};
export const tagManagerProxy = async (req: Request, res: Response) => {
try {
const response = await axios.get(`${GTM_URL}?id=${req.params.script}`, {
responseType: 'stream'
});
// Set appropriate headers
res.setHeader('Content-Type', 'application/javascript');
res.setHeader('Cache-Control', 'public, max-age=3600');
response.data.pipe(res);
} catch (error) {
console.error('Tag Manager proxy error:', error);
res.status(500).send('Error loading tag manager');
}
};``import { useEffect } from 'react';
interface AnalyticsProps {
measurementId: string;
}
export const Analytics: React.FC<AnalyticsProps> = ({ measurementId }) => {
useEffect(() => {
// Load analytics script through proxy
const script = document.createElement('script');
script.async = true;
script.src = import { Analytics } from './analytics/Analytics';
const App = () => {
return (
<>
<Analytics measurementId="G-22P31JZKV2" />
{/* Rest of your app */}
</>
);
};
export default App;interface Window {
dataLayer: any[];
gtag: (...args: any[]) => void;
}PLAUSIBLE_SITE_ID