Add Google Analytics 4 to a Lovable app by loading the gtag.js snippet in your HTML head and creating a Supabase Edge Function that calls the GA4 Measurement Protocol for server-side event tracking. Store your GA4 Measurement ID in Cloud → Secrets as VITE_GA4_MEASUREMENT_ID (public, safe for frontend), and store the GA4 API Secret in Cloud → Secrets for Edge Function use only.
Adding Google Analytics 4 to Your Lovable App
Google Analytics 4 is the most widely used web analytics platform in the world, and for good reason — it provides free, comprehensive data about where your users come from, what they do in your app, and where they leave. For Lovable app builders, GA4 answers acquisition questions that product-focused tools like Mixpanel are not designed for: which marketing channels drive the most signups, which landing pages convert best, and how organic search traffic compares to paid campaigns. GA4's integration with Google Search Console, Google Ads, and Looker Studio makes it the analytical backbone of any app that depends on organic or paid growth.
GA4 uses a dual-layer tracking architecture that maps neatly onto Lovable's security model. The client-side gtag.js snippet loads from Google's CDN and handles all browser-visible events automatically — pageviews, scroll depth, outbound link clicks, and session data. This snippet uses your Measurement ID (a public identifier formatted like G-XXXXXXXXXX) that is safe to embed in frontend code. For backend events — payment completions, API-triggered conversions, and server-side form submissions — GA4's Measurement Protocol allows your Supabase Edge Function to send events directly to Google's collection servers using a secret API key that must stay in Cloud → Secrets.
Lovable's security infrastructure blocks approximately 1,200 hardcoded API keys daily, and GA4's Measurement Protocol API Secret falls squarely in the category of credentials that must never appear in client-side code. The SOC 2 Type II certified Cloud → Secrets panel is the only correct location for this key. Your public Measurement ID, however, can be configured as a VITE_-prefixed build environment variable since it is intentionally public — similar to how the Google Analytics tracking ID has always been embedded in HTML.
Integration method
Google Analytics 4 integrates with Lovable through two complementary layers. The client-side gtag.js snippet loads from Google's CDN and tracks pageviews, scroll depth, and outbound clicks automatically. A Supabase Edge Function uses GA4's Measurement Protocol to send server-side events — purchase confirmations, form submissions, and backend conversions — that must not rely on the browser being open. Your GA4 Measurement ID is a public identifier safe for the frontend, while the Measurement Protocol API Secret stays encrypted in Cloud → Secrets.
Prerequisites
- A Lovable account with an existing project that has Supabase configured
- A Google Analytics 4 account — free at analytics.google.com — with a web data stream created for your app
- Your GA4 Measurement ID (formatted as G-XXXXXXXXXX) from Admin → Data Streams → your stream → Measurement ID
- A GA4 Measurement Protocol API Secret from Admin → Data Streams → your stream → Measurement Protocol → Create, for server-side event tracking
- Basic familiarity with browser developer tools to verify that GA4 events are firing correctly
Step-by-step guide
Create a GA4 property and get your Measurement ID and API Secret
Create a GA4 property and get your Measurement ID and API Secret
Before adding tracking to your Lovable app, you need a GA4 property configured for your application. Log in to Google Analytics at analytics.google.com. If you do not already have a GA4 property for your app, click Admin in the bottom-left corner, then click Create Property in the top-left of the Admin panel. Enter your property name (your app name works well), select your reporting time zone and currency, and click Next. On the Business Details page, select your industry category and business size, then click Next. On the Business Objectives page, select what you want to measure — for a SaaS app, 'Examine user behavior' and 'Generate leads' are usually the most relevant. Click Create. Accept the Terms of Service. Next, create a web data stream. Under Data collection and modification in the Admin panel, click Data Streams, then click Add stream and choose Web. Enter your app's URL — if you are still in development, use your Lovable preview URL. Enter a stream name and click Create stream. On the stream details page, you will see your Measurement ID formatted as G-XXXXXXXXXX. Copy this value — you will add it to Lovable as an environment variable. For server-side event tracking via the Measurement Protocol, you need an API Secret. Still on the web data stream details page, scroll down to find Measurement Protocol API secrets and click the arrow to expand it. Click Create. Give the secret a nickname like 'lovable-backend' and click Create. Copy the secret value shown — you will only see it once. Store it immediately. Now go to your Lovable project, click the + icon next to Preview to open the Cloud tab, click Secrets, and add two entries: VITE_GA4_MEASUREMENT_ID with your G-XXXXXXXXXX value, and GA4_API_SECRET with your Measurement Protocol API secret.
Pro tip: The Measurement ID (G-XXXXXXXXXX) is a public identifier — it is safe to use with the VITE_ prefix so it is accessible in your React components. The Measurement Protocol API Secret is sensitive and must only be used in Edge Functions via Deno.env.get().
Expected result: Your GA4 property has a web data stream configured. VITE_GA4_MEASUREMENT_ID and GA4_API_SECRET are stored in Lovable Cloud Secrets. The GA4 property shows a green 'Receiving data' indicator in the Admin panel (this may take a few minutes after adding the snippet).
Add the gtag.js snippet to your Lovable app for client-side tracking
Add the gtag.js snippet to your Lovable app for client-side tracking
The GA4 gtag.js snippet needs to load in the HTML head of your Lovable application. In a Vite + React project, the right place is the index.html file in your project root — this is the HTML shell that wraps your entire React app, and scripts placed here load on every page. Ask Lovable to add the snippet via the chat interface, specifying your Measurement ID. The snippet consists of two parts: a script tag that loads the gtag.js library asynchronously from Google's CDN, and an inline script that initializes the gtag function with your Measurement ID and calls config to begin tracking. Once loaded, gtag automatically tracks pageviews for each initial page load. However, since Lovable apps use React Router for client-side navigation, route changes do not trigger full page reloads — you need to manually call gtag('event', 'page_view') on route changes to track SPA navigation. Create a useGoogleAnalytics hook that listens to React Router's location changes and sends a page_view event to GA4 on each navigation. Import this hook in your root App component so it runs throughout the entire session. The hook reads the Measurement ID from the VITE_GA4_MEASUREMENT_ID environment variable using import.meta.env.VITE_GA4_MEASUREMENT_ID. This approach handles both the initial pageview and all subsequent client-side navigations correctly, giving you accurate session and pageview data in GA4's reports. For sending custom events from components, use the global gtag function directly: window.gtag('event', 'event_name', { parameter: value }). GA4's enhanced measurement automatically tracks scroll depth, outbound clicks, file downloads, and site search — check Admin → Data Streams → your stream → Enhanced measurement to see which ones are enabled and configure them as needed.
Add the Google Analytics 4 gtag.js snippet to index.html using the Measurement ID from import.meta.env.VITE_GA4_MEASUREMENT_ID. Create a src/hooks/useGoogleAnalytics.ts hook that uses React Router's useLocation to send a 'page_view' event to GA4 on every route change. Add the hook to App.tsx so pageviews are tracked throughout the app.
Paste this in Lovable chat
1// src/hooks/useGoogleAnalytics.ts2import { useEffect } from 'react';3import { useLocation } from 'react-router-dom';45declare global {6 interface Window {7 gtag: (...args: unknown[]) => void;8 }9}1011export function useGoogleAnalytics() {12 const location = useLocation();13 const measurementId = import.meta.env.VITE_GA4_MEASUREMENT_ID;1415 useEffect(() => {16 if (!measurementId || typeof window.gtag !== 'function') return;1718 window.gtag('event', 'page_view', {19 page_path: location.pathname + location.search,20 page_title: document.title,21 });22 }, [location, measurementId]);23}2425// Usage in App.tsx:26// import { useGoogleAnalytics } from '@/hooks/useGoogleAnalytics';27// function App() { useGoogleAnalytics(); return <Router>...</Router>; }Pro tip: GA4's enhanced measurement settings automatically track scroll depth (90% scroll events), outbound link clicks, and site search. Check your data stream settings to enable these — they add valuable behavioral data without any additional code.
Expected result: Your Lovable app loads the GA4 gtag.js snippet. Navigating between pages triggers page_view events. Opening GA4's Realtime report shows active users and page_view events appearing within seconds of browsing your app.
Send custom conversion events from React components
Send custom conversion events from React components
Beyond automatic pageviews, GA4's value comes from tracking meaningful user actions as custom events. GA4's event model uses a flat structure: an event name string and up to 25 key-value parameter pairs per event. Some event names are reserved by Google for enhanced e-commerce (purchase, add_to_cart, begin_checkout) and should only be used with their expected parameter schemas. For custom app-specific actions, use descriptive snake_case names like 'sign_up', 'feature_used', 'report_exported', or 'subscription_started'. Create a centralized analytics utility in your project so all GA4 tracking calls go through a single typed interface. This approach makes it easy to add additional analytics services later and ensures consistent event naming across the codebase. The utility should check that the gtag function exists before calling it (to handle the case where the script has not loaded yet or is blocked by an ad blocker) and should read the Measurement ID from the environment variable to ensure correct configuration. For conversion tracking, mark specific events as conversions in your GA4 Admin panel: go to Admin → Events → click the toggle next to any event to mark it as a conversion. Common conversions for Lovable apps include sign_up, purchase, lead (for lead generation apps), and tutorial_complete. GA4 will then track these events in the Conversions report and allow you to optimize Google Ads campaigns toward these goals. Add GA4 tracking calls at the most important user actions in your app: form submission success, button clicks that initiate key workflows, and feature activations. Each event should include relevant parameters — for example, a 'file_exported' event might include the file format and number of items exported.
Create a src/lib/ga4.ts utility that exports a trackEvent function. The function should call window.gtag('event', eventName, parameters) if gtag is available and VITE_GA4_MEASUREMENT_ID is set. Add trackEvent calls for: 'sign_up' on account creation, 'login' on authentication, 'feature_used' with a feature_name parameter when key features are activated. Export a trackConversion function for purchase and lead events.
Paste this in Lovable chat
1// src/lib/ga4.ts2declare global {3 interface Window {4 gtag: (...args: unknown[]) => void;5 dataLayer: unknown[];6 }7}89const GA_ID = import.meta.env.VITE_GA4_MEASUREMENT_ID;1011function isGtagAvailable(): boolean {12 return !!GA_ID && typeof window !== 'undefined' && typeof window.gtag === 'function';13}1415export function trackEvent(16 eventName: string,17 parameters?: Record<string, string | number | boolean>18) {19 if (!isGtagAvailable()) return;20 window.gtag('event', eventName, parameters);21}2223export function trackConversion(24 transactionId: string,25 value: number,26 currency = 'USD',27 items?: Array<{ id: string; name: string; price: number; quantity: number }>28) {29 if (!isGtagAvailable()) return;30 window.gtag('event', 'purchase', {31 transaction_id: transactionId,32 value,33 currency,34 items: items ?? [],35 });36}3738export function setUserProperties(properties: Record<string, string | number>) {39 if (!isGtagAvailable()) return;40 window.gtag('set', 'user_properties', properties);41}Pro tip: GA4 has a limit of 500 distinct event names per property. Use generic event names with descriptive parameters rather than creating a unique event name for every user action — for example, use 'feature_used' with a 'feature_name' parameter rather than 'used_export_feature', 'used_import_feature', etc.
Expected result: Custom events appear in GA4's Realtime report as you perform tracked actions in the app. The Events report (under Reports → Engagement) shows event counts accumulating. Events marked as conversions appear in the Conversions report.
Create a Supabase Edge Function for GA4 Measurement Protocol
Create a Supabase Edge Function for GA4 Measurement Protocol
The GA4 Measurement Protocol allows server-side event tracking — events sent directly from your Edge Functions to GA4's collection servers without any browser involvement. This is essential for tracking events that occur on the backend: successful Stripe payment confirmations, email delivery events, scheduled job completions, and any conversion that should be recorded even if the user has navigated away or closed their browser. The Measurement Protocol endpoint is https://www.google-analytics.com/mp/collect and accepts POST requests with your Measurement ID and API Secret as query parameters. The request body is a JSON object containing a client_id (an anonymous identifier for the user), optionally a user_id (the authenticated user's ID), and an array of events with their parameters. The client_id is critical — it must be consistent across sessions for the same user so GA4 can correctly attribute events to user sessions. For server-side events triggered by authenticated users, use a combination of a UUID stored in your Supabase database for the user. For events with no user context (like unauthenticated webhooks), generate a stable client_id from the transaction ID or order ID. Create the Edge Function in Lovable using the chat interface. The function accepts a POST request from your frontend or other Edge Functions with the event name and parameters, reads the GA4_API_SECRET and VITE_GA4_MEASUREMENT_ID from Deno.env.get(), and forwards the event to Google's Measurement Protocol endpoint. Handle CORS headers so the function can be called from the browser if needed. Always return HTTP 200 from this function regardless of whether the GA4 API call succeeded — analytics failures should never block user workflows.
Create a Supabase Edge Function called 'ga4-track' that accepts a POST request with event_name, client_id, optional user_id, and optional parameters. Forward the event to the GA4 Measurement Protocol at https://www.google-analytics.com/mp/collect using GA4_MEASUREMENT_ID and GA4_API_SECRET from Deno environment secrets. Return 200 even if the GA4 call fails. Include CORS headers.
Paste this in Lovable chat
1// supabase/functions/ga4-track/index.ts2import { serve } from 'https://deno.land/std@0.168.0/http/server.ts';34const corsHeaders = {5 'Access-Control-Allow-Origin': '*',6 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',7};89serve(async (req) => {10 if (req.method === 'OPTIONS') {11 return new Response('ok', { headers: corsHeaders });12 }1314 try {15 const measurementId = Deno.env.get('VITE_GA4_MEASUREMENT_ID');16 const apiSecret = Deno.env.get('GA4_API_SECRET');1718 if (!measurementId || !apiSecret) {19 console.error('GA4 credentials not configured');20 return new Response(JSON.stringify({ success: false }), {21 status: 200,22 headers: { ...corsHeaders, 'Content-Type': 'application/json' },23 });24 }2526 const { event_name, client_id, user_id, parameters = {} } = await req.json();2728 if (!event_name || !client_id) {29 return new Response(30 JSON.stringify({ error: 'event_name and client_id are required' }),31 { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }32 );33 }3435 const payload: Record<string, unknown> = {36 client_id,37 events: [{ name: event_name, params: { engagement_time_msec: 100, ...parameters } }],38 };3940 if (user_id) payload.user_id = user_id;4142 const url = `https://www.google-analytics.com/mp/collect?measurement_id=${measurementId}&api_secret=${apiSecret}`;4344 const response = await fetch(url, {45 method: 'POST',46 headers: { 'Content-Type': 'application/json' },47 body: JSON.stringify(payload),48 });4950 console.log('GA4 Measurement Protocol response status:', response.status);5152 return new Response(JSON.stringify({ success: true }), {53 headers: { ...corsHeaders, 'Content-Type': 'application/json' },54 });55 } catch (error) {56 console.error('GA4 track error:', error);57 return new Response(JSON.stringify({ success: false }), {58 status: 200,59 headers: { ...corsHeaders, 'Content-Type': 'application/json' },60 });61 }62});Pro tip: The GA4 Measurement Protocol returns HTTP 204 No Content on success — do not treat a 204 response as an error. Use Google's Measurement Protocol Validation Server (https://www.google-analytics.com/debug/mp/collect) during development to verify your event payloads are correctly formatted before sending to the production endpoint.
Expected result: The ga4-track Edge Function is deployed. Calling it with a valid event_name and client_id results in the event appearing in GA4's Realtime report within seconds. The function returns 200 even when GA4's API is unreachable.
Configure GA4 goals and verify end-to-end tracking
Configure GA4 goals and verify end-to-end tracking
With both client-side and server-side tracking implemented, configure GA4 to surface the most important metrics and verify that all tracking is working correctly end-to-end. Start with the GA4 DebugView — it provides a real-time stream of every event your implementation sends, with full parameter details, making it easy to spot missing parameters, misspelled event names, or events firing at the wrong time. To enable DebugView for your browser session, open your Lovable app in Chrome, open Developer Tools, and install the Google Analytics Debugger Chrome extension — it activates GA4's debug mode which sends events to DebugView instead of production data. In GA4, navigate to Admin → DebugView. You will see a timeline of events as you interact with your app, with each event expanded to show all parameters. Verify that page_view events fire on every route change, that your custom events fire at the right times, and that the client_id is consistent across events in the same session. Next, mark your key conversion events. Go to Admin → Events. You will see all events GA4 has received from your app. Find your most important conversion events (sign_up, purchase, lead) and click the toggle in the 'Mark as conversion' column to enable conversion tracking. These events now appear in the Conversions report and can be used as optimization targets for Google Ads campaigns. Finally, set up your first GA4 Exploration report. Go to Explore → Blank Exploration. Add 'Event name' as a dimension and 'Event count' and 'Conversions' as metrics. This gives you a complete picture of all events your app is sending and their conversion rates. For complex GA4 implementations or building internal analytics dashboards using the GA4 Data API, RapidDev's team can help architect the event taxonomy and build the Edge Function infrastructure needed to query and display GA4 data inside your Lovable app.
Pro tip: GA4 data is not available in the standard reports until 24-48 hours after events are sent — but Realtime reports show data within seconds. Use Realtime during development to verify tracking, and use the standard reports for historical analysis once data has had time to process.
Expected result: GA4 DebugView shows all events with correct parameters. Conversion events are marked in the GA4 Admin panel. The Realtime report shows active users and current page paths. The Exploration report shows event counts accumulating across all tracked events.
Common use cases
Track signup and activation funnel for acquisition optimization
Instrument the complete funnel from landing page visit through account creation to first meaningful action. GA4's funnel exploration report shows exactly which step has the highest drop-off, and the acquisition report shows which traffic source drives users who actually complete activation. This data directly informs where to spend marketing budget.
Add Google Analytics 4 event tracking to the signup and onboarding funnel. Track 'sign_up' when a user creates an account with a method property (email or google). Track 'tutorial_complete' when they finish onboarding. Track 'first_value' when they complete the first meaningful action in the app. Use the gtag() function from the GA4 snippet already loaded in index.html.
Copy this prompt to try it in Lovable
Track e-commerce conversions server-side via Measurement Protocol
Send purchase events to GA4 from the Stripe webhook Edge Function so conversions are always captured regardless of browser behavior. Server-side purchase tracking is more accurate than client-side because it is not affected by ad blockers, browser closures, or navigation away from the confirmation page. GA4's revenue reports show true conversion value.
Create a Supabase Edge Function that sends a 'purchase' event to the GA4 Measurement Protocol when a Stripe payment succeeds. Include the transaction_id, value, currency, and items array in the event payload. Use the GA4_MEASUREMENT_ID and GA4_API_SECRET from Cloud Secrets. Call this from the existing Stripe webhook handler after payment confirmation.
Copy this prompt to try it in Lovable
Embed GA4 Data API charts inside the Lovable app
Build an in-app analytics dashboard that shows users their own engagement metrics pulled from GA4 via the Data API. A Supabase Edge Function authenticates with a Google Service Account and calls the GA4 Data API to fetch pageviews, active users, and conversion counts. Display these as summary cards or charts inside your Lovable app.
Create a Supabase Edge Function that calls the GA4 Data API to fetch pageviews and active users for the last 30 days. Authenticate using a Google Service Account JSON key stored as GA4_SERVICE_ACCOUNT_KEY in Cloud Secrets. Return the data as JSON so the frontend can display it in a stats dashboard. Create a React component that calls this Edge Function and displays the metrics.
Copy this prompt to try it in Lovable
Troubleshooting
GA4 Realtime report shows no data after adding the gtag.js snippet
Cause: The snippet was not placed in the correct location in index.html, the VITE_GA4_MEASUREMENT_ID environment variable is not configured as a build variable, or an ad blocker is intercepting requests to googletagmanager.com.
Solution: Open the browser's Network tab and filter for 'google-analytics' or 'googletagmanager'. If no requests appear, the snippet did not load — verify the snippet is in the HTML head before the closing head tag and that the measurement ID is not undefined (check the rendered source for your G-XXXXXXXXXX ID). If requests appear but show blocked status, disable your ad blocker for testing. For production, consider routing GA4 requests through your own domain using the Measurement Protocol Edge Function to bypass blockers.
Page views are only tracked on the initial load, not on navigation between routes
Cause: React Router uses client-side navigation that does not trigger full page reloads, so GA4's automatic pageview tracking only fires once. The useGoogleAnalytics hook is either missing, not added to App.tsx, or the useLocation hook is not updating correctly.
Solution: Verify the useGoogleAnalytics hook is imported and called in the root App component (the component that contains your React Router setup). Check that the hook's useEffect dependency array includes the location object from useLocation. Navigate between pages and watch the GA4 Realtime report — each navigation should trigger a page_view event.
Measurement Protocol Edge Function returns success but events do not appear in GA4
Cause: The client_id format is invalid (must be a non-empty string), the engagement_time_msec parameter is missing (GA4 requires this for session attribution), or the API Secret does not match the property's Measurement ID.
Solution: Use the GA4 Measurement Protocol Validation endpoint (replace /mp/collect with /debug/mp/collect in the URL) and check the validationMessages array in the response. Common issues are: client_id must be a non-empty string, events[0].params.engagement_time_msec must be set to at least 1, and the api_secret must match the data stream that owns the measurement_id. Verify both secrets in Cloud → Secrets are from the same GA4 data stream.
1// Add to Edge Function payload to debug validation errors:2const debugUrl = `https://www.google-analytics.com/debug/mp/collect?measurement_id=${measurementId}&api_secret=${apiSecret}`;3const debugResponse = await fetch(debugUrl, { method: 'POST', body: JSON.stringify(payload) });4const debugResult = await debugResponse.json();5console.log('Validation result:', JSON.stringify(debugResult));GA4 shows duplicate conversions or inflated event counts
Cause: The trackEvent function is being called inside a React component that re-renders on every state change, or the useGoogleAnalytics hook has an incorrect dependency array causing the page_view event to fire multiple times per navigation.
Solution: Move trackEvent calls out of the component render function and into event handlers or useEffect hooks with correct dependency arrays. For the page_view hook, ensure the useEffect only has the location object in its dependency array — not the entire location object's children properties. Use the GA4 DebugView to watch event firing in real time and identify exactly when duplicates occur.
Best practices
- Use a consistent event naming convention across your entire app — GA4 recommends snake_case event names like 'sign_up', 'feature_used', 'checkout_started'. Avoid spaces, hyphens, or camelCase to prevent fragmented data in reports.
- Always include the engagement_time_msec parameter in Measurement Protocol events — without it, GA4 may not count the event toward active user sessions, causing discrepancies between client-side and server-side data.
- Store the Measurement ID as a VITE_-prefixed environment variable for the frontend and as a plain secret for Edge Functions — never hardcode the G-XXXXXXXXXX string in your component code since it becomes difficult to manage across development, staging, and production environments.
- Configure Google Signals in GA4 (Admin → Data Settings → Data Collection) to enable cross-device tracking and demographic reporting — this requires users to be signed in to Google but significantly improves audience insights at no extra cost.
- Set up data retention in GA4 at 14 months (Admin → Data Settings → Data Retention) — the default is 2 months, which causes historical data to disappear from Exploration reports after 60 days.
- Use GA4's custom dimensions to attach user properties (plan, account age, feature flags) to every session — configure these in Admin → Custom Definitions → Custom Dimensions before tracking them, as GA4 does not retroactively process custom dimensions.
- Create a separate GA4 property or data stream for development to prevent test events from contaminating production analytics data — use VITE_GA4_MEASUREMENT_ID set to the development stream ID in your .env.local file.
- Enable IP anonymization by default (GA4 does this automatically) and review your privacy policy to disclose GA4 tracking — many jurisdictions require explicit disclosure of analytics cookies and data collection.
Alternatives
Choose Mixpanel when you need user-level behavioral analytics with event funnels and cohort retention — Google Analytics excels at acquisition and SEO traffic analysis while Mixpanel is better for understanding how individual users interact with product features.
Choose Amplitude when you need advanced behavioral cohort analysis and predictive retention modeling — GA4 covers acquisition and basic engagement while Amplitude provides deeper product analytics with ML-powered insights.
Choose Segment when you want to send analytics data to multiple destinations including GA4 from a single integration — Segment acts as a customer data platform that can route events to GA4, Mixpanel, and hundreds of other tools simultaneously.
Frequently asked questions
Is Google Analytics 4 free to use with a Lovable app?
GA4 is free for standard use — there is no cost to add it to your Lovable app and no charge for the volume of events you send. The GA4 360 paid tier ($150,000+/year) adds higher data freshness, more custom dimensions, and BigQuery export for enterprise-scale data needs, but the free tier is more than sufficient for most Lovable apps.
Why does GA4 show fewer conversions than I tracked in my app?
GA4 uses statistical modeling to fill in gaps where data is incomplete due to ad blockers, cookie consent rejections, or browser restrictions. This means GA4's reported conversion numbers may be lower than your actual count from Supabase. Use the Measurement Protocol Edge Function approach for critical conversion events (purchases, signups) so they are tracked server-side and not subject to browser-side blocking. Compare GA4 data against your Supabase transaction table as the source of truth for revenue.
How do I track users across sessions in GA4?
GA4 uses the client_id stored in a first-party cookie (_ga) to identify returning users across sessions. For authenticated users, you can also set a user_id with window.gtag('set', {user_id: userId}) after login — GA4 then links sessions across devices when the same user logs in from different browsers. The user_id must be a non-personally-identifiable string (use your Supabase user UUID, not the user's email address).
What is the difference between GA4 events and conversions?
In GA4, every tracked action is an event, and conversions are simply events you have marked as important business outcomes. You mark events as conversions in Admin → Events by toggling the 'Mark as conversion' switch. Conversion events then appear in the dedicated Conversions report and can be used as optimization targets for Google Ads. There is no difference in how the events are sent from your app — the distinction is purely in how GA4 reports them.
Can I see GA4 data inside my Lovable app without leaving the browser?
Yes, using the GA4 Data API. Create a Supabase Edge Function that authenticates with a Google Service Account and calls the GA4 Data API to fetch metrics like active users, pageviews, and conversion counts. The Edge Function stores the service account credentials in Cloud Secrets and returns the data as JSON for your React components to display. This lets you build an in-app analytics dashboard that shows real GA4 data to your users or your team.
Does GA4 work with Lovable's preview environment?
GA4 will track events from Lovable's preview environment, but the preview runs in an iframe which some browsers restrict for cookie-based tracking. For reliable testing, use GA4's DebugView (which works without cookies) and the Measurement Protocol Edge Function. It is best practice to use a separate GA4 property or data stream for development so test events do not appear in your production analytics.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation