Installation guides
SvelteKit
Add ProductLense to src/app.html in a SvelteKit app, then identify signed-in users from the root layout.
In SvelteKit, every page is rendered into src/app.html, so the script goes in its head once. Client-side navigation is recorded through the history API, and prerendered or server-rendered pages work the same way.
Add the script
Paste the queue stub and the script tag before %sveltekit.head%. Replace SITE_ID with the id from Settings → Sites in the ProductLense dashboard.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<script>window.productlense=window.productlense||function(){(window.productlense.q=window.productlense.q||[]).push(arguments)}</script>
<script defer data-site="SITE_ID" src="https://api.productlense.app/a.js"></script>
%sveltekit.head%
</head>
<body>
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>If you set a Content Security Policy in svelte.config.js (kit.csp), add https://api.productlense.app to script-src and connect-src. In nonce mode, give the inline stub nonce="%sveltekit.nonce%"; otherwise drop the stub and call window.productlense?.(...) with optional chaining.
Identify users
Declare the global once:
declare global {
interface Window {
productlense?: (...args: unknown[]) => void;
}
}
export {};Then identify from the root layout, with the signed-in user from your layout data:
<script lang="ts">
let { data, children } = $props();
$effect(() => {
if (data.user) window.productlense?.('identify', data.user.id);
});
</script>
{@render children()}Use the same id you store on the customer in your billing provider; see how payments are attributed.
Custom events
<button onclick={() => window.productlense?.('event', 'Upgrade clicked', { plan: 'growth' })}>
Upgrade
</button>See custom events for naming rules.
Verify your installation
- Deploy, then open your site in a normal browser window.
- Open the Live page in the ProductLense dashboard. Your visit appears within a few seconds.
- In the browser's developer tools, the Network tab shows a
POSTtohttps://api.productlense.app/api/ewith status204. Navigate to another page: a second pageview follows.
vite dev runs on localhost, where nothing is sent unless you add data-dev="true" to the tag. Ad blockers in your own browser may block the request. If the visit does not appear, follow Verify your installation.