Webflow forms can be tracked as Zenovay goals using one of two approaches. Pick the one that matches your form's redirect behaviour. Goals live in the Journeys tab, which is available on the Pro plan and above.
Step 0 — Install the tracker
If you haven't yet, paste the Zenovay tracking script into Project Settings → Custom Code → Head Code in Webflow:
<script
defer
data-tracking-code="YOUR_TRACKING_CODE"
src="https://api.zenovay.com/z.js"
></script>
Publish the site and confirm in your Zenovay dashboard that pageviews are flowing.
Approach 1 — URL-match goal (simple)
Use this when your form redirects to a thank-you page after submission.
- In Webflow, set the form's Form Settings → Redirect URL to a unique success page, e.g.
/contact-thanks. - In Zenovay, open your website's dashboard and go to the Journeys tab, then the Goals sub-tab.
- Click New goal and pick A page visit (this matches against the page address).
- Pick the page from the list of your pages, or enter it with a match type, for example Is exactly with
/contact-thanks(or whatever you set as the redirect). - Give the goal a name and click Create goal.
Every visit to the thank-you page now counts as a conversion. This is the simplest and most reliable approach.
Approach 2 — Custom event (no redirect)
Use this when your form stays on the same page and shows an inline success message.
Webflow swaps the form for a .w-form-done success block after a successful AJAX submission. Watch for that block becoming visible and send a Zenovay custom event. Add this to Project Settings → Custom Code → Footer Code:
<script>
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('form').forEach(form => {
form.addEventListener('submit', () => {
// Webflow validates client-side; the success message appears after AJAX completes.
// We listen for the success block becoming visible.
const successEl = form.parentElement.querySelector('.w-form-done');
if (!successEl) return;
const observer = new MutationObserver(() => {
if (successEl.style.display !== 'none' && successEl.offsetHeight > 0) {
window.zenovay && window.zenovay('track', 'form_submitted', {
form_id: form.getAttribute('data-name') || form.id || 'unknown'
});
observer.disconnect();
}
});
observer.observe(successEl, { attributes: true, childList: true, subtree: true });
});
});
});
</script>
The custom-event call is window.zenovay('track', '<event_name>', { ...properties }) — the first argument is the literal command 'track', then your event name, then an optional properties object.
Then create a custom-event goal in Zenovay:
- Open your website's dashboard, go to the Journeys tab → Goals sub-tab, and click New goal.
- Pick An event from your code.
- Pick
form_submittedfrom the list of events your site has sent, or type it. Upper and lower case don't matter, but otherwise it must match the name you send in the script. - Give the goal a name and click Create goal.
If you want to track just one form, send a distinct event name per form (e.g. contact_form_submitted) and create a goal for each.
Verifying it works
Submit the form on your live site. Within ~30 seconds:
- New activity should appear on the Live View tab of your website's dashboard.
- The goal's Conversions should go up under the Journeys tab → Goals sub-tab, and your visit appears under Latest conversions in the goal's details.
Common pitfalls
- Form fails validation — Approach 1 won't fire because there's no redirect. Approach 2 won't fire because the success block stays hidden. This is correct behaviour — you only want successful submissions counted.
- Webflow CMS forms — same approach works; the
data-nameattribute may differ from the form name in the editor. - Multiple forms on one page — both approaches handle this. In Approach 2, the
form_idproperty (or a per-form event name) lets you tell them apart in the dashboard.