Installation guides
Remix
Add ProductLense to a Remix or React Router framework app in app/root.tsx, then identify signed-in users from a loader.
In Remix (and React Router in framework mode), every page renders through app/root.tsx, so the script goes in its <head> once. Client-side navigations use the history API and are recorded as pageviews automatically.
Add the script
Replace SITE_ID with the id from Settings → Sites in the ProductLense dashboard.
import { Links, Meta, Outlet, Scripts, ScrollRestoration } from '@remix-run/react';
export default function App() {
return (
<html lang="en">
<head>
<Meta />
<Links />
<script
dangerouslySetInnerHTML={{
__html: 'window.productlense=window.productlense||function(){(window.productlense.q=window.productlense.q||[]).push(arguments)}',
}}
/>
<script defer data-site="SITE_ID" src="https://api.productlense.app/a.js" />
</head>
<body>
<Outlet />
<ScrollRestoration />
<Scripts />
</body>
</html>
);
}The inline stub is a fixed string with no user data in it. If your site sends a Content-Security-Policy, allow it by hash or nonce; see Content Security Policy. In React Router v7 framework mode the imports come from react-router instead of @remix-run/react; the tags are the same.
Identify users
Return the user id from the root loader and call identify once it is known:
import { useEffect } from 'react';
import { useLoaderData } from '@remix-run/react';
export function ProductLenseIdentify() {
const { userId } = useLoaderData<{ userId: string | null }>();
useEffect(() => {
if (userId) window.productlense?.('identify', userId);
}, [userId]);
return null;
}Render <ProductLenseIdentify /> inside <body>. 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
- Build and 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. Follow a link to another route: a second pageview follows.
The development server 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.