Add Zenovay to any Framer site through Site Settings → Custom Code. The snippet only fires on the published site — this is expected behaviour.
Custom Code only takes effect on the published Framer site. Preview always ignores Custom Code. Always test the live URL, not the editor preview.
Quick Start
- Copy your tracking snippet from the Zenovay dashboard.
- In Framer, open Site Settings → General → Custom Code.
- Paste it into Start of
<head>tag. - Click Publish in the top-right corner.
Installation
Site-wide Custom Code (recommended)
- Open your project in Framer.
- Click Site Settings (gear icon at the top of the left panel).
- Open the General tab.
- Scroll to Custom Code.
- Paste this snippet into Start of
<head>tag:
<script defer data-tracking-code="YOUR_TRACKING_CODE" src="https://api.zenovay.com/z.js"></script>
- Click outside the field to save automatically.
- Click Publish in the top-right.
Per-page Custom Code
For tracking only on specific pages:
- Select the page in the Pages panel.
- Open the page's right-side settings.
- Scroll to Custom Code → Start of
<head>tag. - Paste the snippet.
- Publish.
Don't combine site-wide and per-page snippets — you'll double-count.
Verify your installation
- Open the published Framer URL (
*.framer.appor your custom domain) in incognito. - View source and look for
<script defer data-tracking-code=...>in the<head>. - Check the Zenovay real-time view — your visit appears within ~30 seconds.
SPA navigation is handled automatically
Framer renders pages as a React SPA. The Zenovay tracker (v2+) listens for history.pushState and fires a pageview on every route change automatically. You don't need to call window.zenovay('trackPageView') manually.
Tracking custom events via Code Overrides
Create a Code Override that wraps any Framer component:
import type { ComponentType } from 'react';
export function withCtaTracking(Component): ComponentType {
return (props) => (
<Component
{...props}
onClick={(e) => {
props.onClick?.(e);
// @ts-ignore — global injected by tracker
window.zenovay?.('track', 'cta_clicked', {
location: props.id || 'unknown',
page: window.location.pathname,
});
}}
/>
);
}
Apply via Frame → Code Overrides → withCtaTracking.
Tracking form submissions
Attach a delegate listener on document to capture every native form submit:
import { useEffect } from 'react';
export function useTrackFormSubmits() {
useEffect(() => {
const handler = (e: Event) => {
const form = e.target as HTMLFormElement;
if (!form?.matches('form')) return;
// @ts-ignore
window.zenovay?.('track', 'form_submitted', {
form_id: form.id || form.getAttribute('name') || 'unnamed',
});
};
document.addEventListener('submit', handler, true);
return () => document.removeEventListener('submit', handler, true);
}, []);
return null;
}
Troubleshooting
Preview shows no data. Custom Code only runs on the published site. Always test the live URL.
No data on Free plan. Custom Code requires a paid Framer plan (Mini and above).
Editor traffic polluting analytics. Framer's CMS preview loads with ?framer-publish=true. Filter that query string out using saved segments in your dashboard.
Events fire but pageviews don't on route change. You're on an older tracker version. Re-copy the snippet from your Zenovay dashboard to get the v2 tracker which handles SPA navigation automatically.
Plan requirements
| Plan | Custom Code |
|---|---|
| Free | ❌ |
| Mini | ✅ |
| Basic / Pro / Business | ✅ |
Privacy
For cookieless tracking add data-cookieless="true":
<script defer
data-tracking-code="YOUR_TRACKING_CODE"
data-cookieless="true"
src="https://api.zenovay.com/z.js"></script>
Next steps
- Read the full Framer integration guide on docs.zenovay.com for advanced Code Override patterns.
- Set up conversion goals.
- Need help? Contact [email protected].