Boost Lovable's performance with manual analytics script insertion. Learn how to add meta tags & scripts and follow our best practices.

Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
Analytics scripts must be manually inserted in Lovable because Lovable intentionally treats third‑party tracking as an explicit, repository-level change: there’s no automatic runtime head injection, no terminal/CLI inside the app to run packages or build steps for you, and analytics often require precise placement, secrets, and consent that the platform cannot assume or safely automate.
// Create a new file at docs/analytics-manual-insertion.md with an explanation for the team
// The file should explain why analytics must be manually added, where to keep keys, and when to use GitHub export.
Create file: docs/analytics-manual-insertion.md
Content:
// Explain why analytics scripts must be manually inserted in Lovable
// Keep this focused on reasons (no step-by-step insertion instructions)
# Why analytics scripts must be manually inserted in this Lovable project
- Lovable does not perform automatic head/script injection at preview or deploy time; edits must be explicit in the repository.
- There is no in-app terminal to install packages or run build tasks; integrations that require npm/yarn or build-time changes need GitHub export and local CLI.
- Preview environments have sandboxing/CSP differences that can hide or block third-party trackers; explicit changes avoid confusing preview behavior.
- Secrets (API keys) must be managed through the Lovable Secrets UI, not hard-coded into files; manual insertion ensures keys and consent are handled intentionally.
- Server-side rendering, edge functions, and routing can require specific placement (client-only or server templates), so a human decision is needed.
Checklist for contributors:
// These are high-level items only, not step instructions
- Confirm legal/consent requirements before adding trackers.
- Store sensitive keys in the Secrets UI.
- If a package or build step is required, use GitHub export and complete installs locally.
- Make the change as a repo commit so it goes through review and publish.
This prompt helps an AI assistant understand your setup and guide you through the fix step by step, without assuming technical knowledge.
Paste one of the Lovable prompts below into your Lovable project chat to make Lovable edit the right files, save your analytics ID into Lovable Secrets, and add the meta tags and script tags. After Lovable makes the changes, use Preview to verify and Publish to deploy. Choose the prompt that matches your app structure (static/CRA or Next.js app router).
// Please update the project files as described below.
// Use the Secrets UI to create a secret named ANALYTICS_MEASUREMENT_ID (value should be my GA/analytics ID).
// Then insert meta tags and the analytics script into public/index.html head section.
update file public/index.html
// Find the <head> ... </head> block and add these lines near the top of <head> (after any existing <meta charset>):
// Add description, open graph, and viewport if missing, then load analytics script using the secret.
<!doctype html>
<html lang="en">
<head>
<!-- existing head content preserved -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="<!-- update this description -->" />
<meta property="og:title" content="<!-- update title -->" />
<meta property="og:description" content="<!-- update description -->" />
<meta property="og:type" content="website" />
<!-- Analytics script: uses Lovable Secret ANALYTICS_MEASUREMENT_ID -->
<script async src="https://www.googletagmanager.com/gtag/js?id=%ANALYTICS_MEASUREMENT_ID%"></script>
<script>
// Replace %ANALYTICS_MEASUREMENT_ID% at build/runtime with the secret value from Lovable Secrets UI
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '%ANALYTICS_MEASUREMENT_ID%');
</script>
</head>
<body>
<!-- rest of file preserved -->
</body>
</html>
finish update
// After applying changes, open Preview to confirm meta tags and that the script tag includes the secret value.
// Note: I added %ANALYTICS_MEASUREMENT_ID% placeholders — please ensure you set a Lovable Secret named ANALYTICS_MEASUREMENT_ID and map it in the project's runtime as an environment variable or use Lovable's secret interpolation feature if available.
// Please update or create app/head.tsx (Next.js app router).
// Use the Secrets UI to create a secret named NEXT_PUBLIC_ANALYTICS_ID with the analytics ID value.
// Insert meta tags and insert script tag in the head component, using process.env.NEXT_PUBLIC_ANALYTICS_ID.
create_or_update file app/head.tsx
// If app/head.tsx already exists, merge the head return value; otherwise create this file.
import React from 'react';
export default function Head() {
const id = process.env.NEXT_PUBLIC_ANALYTICS_ID || '%NEXT_PUBLIC_ANALYTICS_ID%'; // placeholder used if env not injected
return (
<>
{/* meta tags */}
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="<!-- update description -->" />
<meta property="og:title" content="<!-- update title -->" />
<meta property="og:description" content="<!-- update description -->" />
{/* analytics script */}
<script async src={`https://www.googletagmanager.com/gtag/js?id=${id}`}></script>
<script dangerouslySetInnerHTML={{
__html: `
// analytics init
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${id}');
`
}} />
</>
);
}
finish update
// After changes, set the Lovable Secret NEXT_PUBLIC_ANALYTICS_ID to your measurement ID and use Preview to verify the head contains the populated ID.
// If your build requires secrets to be exposed as NEXT_PUBLIC_ env vars, use the Secrets UI mapping for runtime/public envs.
Keep metadata and third‑party scripts non-blocking, localize any secret keys to Lovable Secrets (never inline them in public files), and prefer a small, client-only loader that dynamically injects external scripts after page load or when a user opts in. Use Lovable Chat edits + Preview to make the file changes, store secrets via the Secrets UI, and only use GitHub export/sync when you need build-time substitution or server runtime access.
// Chat instruction to Lovable:
// Update public/index.html. Inside the <head>, add:
// 1) non-sensitive meta tags and JSON-LD
// 2) a small inline, non-secret loader snippet (named LOVABLE_DEFER_LOADER)
// Inside </body> (toward end), add a data-driven external loader hook.
// Please do not replace existing tags; insert the new blocks with clear comments.
<!-- LOVABLE: add meta + JSON-LD -->
<meta name="description" content="<!-- LOVABLE: update site description -->">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<script type="application/ld+json">
// {
// // LOVABLE: site structured data; safe to include public info
// }
</script>
<!-- LOVABLE_DEFER_LOADER: does not load analytics automatically -->
<script>
// // Only runs in browsers. Controlled via document.documentElement.dataset.loadAnalytics="true"
(function(){
if (typeof window === 'undefined') return;
function loadExternal(src, attr){
var s = document.createElement('script'); s.src = src; s.async = true;
if(attr) Object.keys(attr).forEach(k=>s.setAttribute(k, attr[k]));
document.body.appendChild(s);
}
window.__lovableLoad = function(){
// // LOVABLE: developers can call window.__lovableLoad() from client code or via Consent UI
// // Example loader entrypoints (replace via Lovable Chat edits, do not hardcode secrets)
// loadExternal('https://example.com/vendor.js');
};
})();
</script>
<!-- LOVABLE: end of insert -->
// Chat instruction to Lovable:
// Create file src/utils/loadExternalScript.js with a single exported function `loadScript(url, opts)`
// Then update your client entry file (e.g., src/main.js or src/main.tsx) to call it only in browser runtime.
// If you cannot detect the exact entry file, list candidate files and ask before editing.
export function loadScript(url, opts){
// // opts: {async:true, defer:true, attrs:{}}
return new Promise((res, rej)=>{
if(typeof document === 'undefined') return rej('no DOM');
var s = document.createElement('script');
s.src = url;
if(opts && opts.async) s.async = true;
if(opts && opts.defer) s.defer = true;
if(opts && opts.attrs) Object.keys(opts.attrs).forEach(k=>s.setAttribute(k, opts.attrs[k]));
s.onload = res; s.onerror = rej;
document.body.appendChild(s);
});
}
// Chat instruction to Lovable:
// Add a file named docs/SECRETS.md that documents required secret names and where they are used.
// Content should include:
// - ANALYTICS_ID : used by client loader via runtime substitution or server-side endpoint
// - Instruction: "Set via Lovable Secrets UI; do not commit values to repo"
From startups to enterprises and everything in between, see for yourself our incredible impact.
Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We’ll discuss your project and provide a custom quote at no cost.