invisit
All posts

By Miraç Berk14 min read

How to add analytics to Webflow, Framer, Squarespace and Wix

Where tracking code goes on each builder, which plan it needs, how page changes and clicks are counted, and the staging traps, tested in November 2026.

A soft 3D website builder canvas with stacked layout blocks and a small script tag sliding into its header, in violet dithered light and shadows.

To add analytics to a Webflow, Framer, Squarespace or Wix site, paste your tool’s script tag into the builder’s site-wide head code, publish, and then limit counting to your own domain, because most builders also serve your site, code included, at a staging or built-in address. All four reserve site-wide code for paid plans, and on Squarespace even the cheapest, Basic, leaves it out.

Builder facts below come from each builder’s own documentation as of November 2026; behaviour comes from our tests on November 3, 2026, with invisit, the cookieless analytics tool we build, on a page with Webflow’s markup and on seven published builder sites. We had no builder accounts, so nothing was tested inside an editor; the last section says what that leaves open.

Where does analytics code go on Webflow, Framer, Squarespace and Wix?

Each builder has one field for code that goes into the head of every page, and that is where an analytics script belongs. As of November 2026:

Builder Site-wide code Plan for custom code Built-in analytics How pages change Attributes on elements Proxy on your domain
Webflow Site settings → Custom code → Head code A Site plan, or a Core, Growth, Agency or Freelancer Workspace Analyze, a paid add-on; local storage Full page loads Element settings → Custom attributes Cloudflare in front (O2O), on a paid Site plan
Framer Project Settings → Custom Code, run Once A paid plan; Framer’s help does not name one Included; no cookies, daily salt Client-side, with pushState Only through a code override Pro with the Advanced Hosting add-on, or Enterprise
Squarespace Code Injection → Header Core, Plus, Advanced and some legacy plans Squarespace Analytics; cookies for up to 2 years Full loads; client-side in some 7.0 templates None; your own HTML in a Code Block None documented
Wix Settings → Custom Code → Head, Load code once A Premium plan, published, with a connected domain Wix Analytics; with a banner, only visitors who accept Full loads on the site we tested None on regular elements Not supported
Carrd Embed element, Hidden, Head Pro Standard, $19 a year Included; cookie-free Sections change only the #fragment Pro Plus, $49 a year None documented

Sources: Webflow (custom code, Analyze, custom attributes, O2O), Framer (custom code, analytics, overrides, reverse proxy), Squarespace (code injection, code blocks, cookies), Wix (custom code, Cloudflare), Carrd (embeds, sections, plans). The page-change column is from our tests below.

Framer’s help never names the plan for custom code; a Framer product specialist answered in Framer’s community that the Free plan cannot add it. Framer also moved the field on December 15, 2025, from Site Settings → General to Project Settings → Custom Code, so older guides, Fathom’s included, point to the old place. Webflow’s own Google Analytics integration needs no paid plan, so a site on the free Starter plan can run GA4, but not a script you paste.

Framer is the only one of the four whose maker says its built-in analytics needs no cookie banner. Squarespace and Wix count visitors with cookies, and Webflow Analyze keeps its data in the browser’s local storage.

Local storage is no way around consent. Article 5(3) of the ePrivacy Directive covers any information stored on the device, and whether a cookieless script needs consent in your country is covered in our cookie banner guide. invisit stores nothing about the visit on the device: in our test page it set no cookies and wrote nothing to localStorage.

On Wix, check one more setting. Custom code is “categorized as essential by default”, which means Wix loads it before consent; choose Analytic under the snippet’s Code Type if your banner should hold it back.

Do page changes on Framer, Wix and Squarespace count as page views?

Yes, in any tool that follows the History API, and three of the sites we tested never needed it: Webflow, Squarespace 7.1 and Wix loaded a new document on every click. Framer and Squarespace 7.0 templates with Ajax loading change pages with pushState, and Carrd sections change only the #fragment.

What happened when we clicked through menus with the invisit tracker running:

Builder (site tested) What a menu click did What invisit recorded
Webflow (a Webflow template) Full page load One page view per page
Framer (two Framer templates) pushState, with the title set afterwards One page view per page, with the new title
Squarespace 7.0 (Brine, Ajax on) replaceState, then pushState, 5 seconds after the click One page view per page, with the new title
Squarespace 7.1 (Nolan) Full page load One page view per page
Wix (a Wix template demo) Full page load; internal links prefetched One page view per page
Carrd (a Carrd template) Only the #fragment changed One page view, for /, whatever the section

On Framer the router changed the address 0.13 seconds after the click and set the new title 1.47 seconds after that. invisit holds a client-side page view until the title changes, for up to two seconds, so the About page view carried the About title, not the home page’s. On Squarespace’s Ajax templates, Back calls replaceState straight after the browser’s popstate; invisit treats a replaceState that keeps the address as part of the same page change, so the Back page view also waits for its title.

Wix does not document how its sites navigate. The page we tested carried a setting named mpaNavigationCompatible, set to true, and a speculation rule tagged mpa-prefetch-eager that prefetches every internal link, which suggests Wix picks full page loads per site and can fall back to client-side navigation. A prefetch downloads the HTML but runs no scripts, so it adds no page views.

Once or on every page visit?

Run the snippet once: Framer’s Once and Wix’s Load code once. A tracker that follows the History API counts client-side page changes by itself. When we added the invisit tag again after each Framer navigation, as Run on every page visit would, nothing changed, because a second copy of the script reuses the running tracker.

Other tools differ. Fathom’s Framer guide adds data-spa="auto" for Framer’s page changes; its Wix guide does not. Plausible follows pushState without settings, and on Carrd its hashBasedRouting: true option counts each section as a page. invisit cannot: the fragment is never part of the address it records, so a Carrd site with sections shows one page. Our single-page app guide compares seven tools on route changes.

To see how your own site navigates, open the browser console on it, run window.probe = 1, click a menu link and run window.probe again. 1 means the page changed client-side; undefined means it reloaded.

How to track button clicks and forms without JavaScript

On Webflow, give the element custom attributes; on Framer, add them through a code override. Squarespace and Wix have no attribute field on their buttons, so use your own HTML in a Squarespace Code Block, or a CSS selector rule that matches the link.

Webflow custom attributes

Select the button or link, open Element settings → Custom attributes, and add data-invisit-event with a name such as cta_clicked. Each data-invisit-prop-<key> attribute you add becomes a string property (events without JavaScript). On our page with Webflow’s markup, sending to the development collector:

  1. A click on the text inside a Link block recorded cta_clicked with location: hero, because the tracker looks for the attribute on the clicked element and every element it sits inside.
  2. On the Form wrapper, the <form> itself, data-invisit-event recorded one event per submit.
  3. On the Form block around it, the same attribute recorded a click event when we clicked into the email field and another on the submit button, and nothing on submit. Put form attributes on the form.
  4. A submit stopped by the browser’s required-field check sent nothing. One that passes the browser counts even if Webflow’s server rejects it afterwards, so for completed submissions, redirect to a thank-you page and count that page.
  5. Without any attribute, a link to Calendly was recorded as outbound_link, and a PDF on Webflow’s asset host, cdn.prod.website-files.com, as file_download.

Umami’s data-umami-event works the same way. Plausible marks events with class names such as plausible-event-name=Signup, and Webflow accepts a class custom attribute only from CMS fields or component properties, so Plausible’s Webflow guide adds the classes with a script keyed on element IDs.

Framer code overrides

Framer has no attribute field, but its developer docs use code overrides to add data attributes to any layer. Create an override file and apply the function to the button under Code Overrides:

Framer: Assets → Code → Tracking.tsx
import { forwardRef, type ComponentType } from 'react'

export function withCtaTracking(Component): ComponentType {
  return forwardRef((props, ref) => (
    <Component
      ref={ref}
      {...props}
      data-invisit-event="cta_clicked"
      data-invisit-prop-location="hero"
    />
  ))
}

We could not run this inside Framer.

On Squarespace, a Code Block takes HTML on every plan, so a link you write yourself, <a href="/book" data-invisit-event="book_clicked">Book a call</a>, carries the attribute. Squarespace documents no way to add one to its own Button blocks.

For the builder’s own buttons, define the event as a rule: a click on an element matching a CSS selector, created through the REST API or by asking an assistant connected to invisit’s MCP server. The tracker fetches rules when it starts, so a new one needs no change to the site. Match the link target, not generated names: Wix warns that its element IDs and class names “may break when a site is re-published”. On the Wix site we tested, links carried the full address, so the selector is a[href="https://www.example.com/book"]; Squarespace’s are relative, as in a[href="/book"]. Rules take exact attribute values only, and a Wix Embed HTML element is an iframe the tracker on the page never sees into.

How to install analytics on each builder

The steps for invisit, with what other tools do differently. The snippet comes from Settings → Installation in the dashboard; keep data-collector, since the script has no default collector.

Webflow

  1. Open Site settings → Custom code and paste the tag into Head code, inside Webflow’s preview markers:
Webflow: Site settings → Custom code → Head code
<!-- EXCLUDE FROM PREVIEW: START -->
<script
  async
  src="https://api.invisit.dev/invisit.js"
  data-site="<site id>"
  data-collector="https://api.invisit.dev"
></script>
<!-- EXCLUDE FROM PREVIEW: END -->
  1. Save and publish. Webflow says custom code takes effect “in preview and comment modes” as well as on the published site; the markers are its documented way to keep a script out of both.
  2. In invisit, add your custom domain under Settings → Collection → Allowed domains, because publishing to yoursite.webflow.io runs the same code.

For GA4, use Site settings → Integrations → Google Analytics and paste the measurement ID; Webflow sends it through Google Tag Gateway. Plausible and Fathom go in Head code like the tag above.

Framer

  1. Open Project Settings → Custom Code, click Add Script, name it, and place it at the end of <head>.
  2. Leave it on all pages and set it to run Once.
  3. Publish. Framer does not load custom code in its preview.
  4. Add your custom domain to allowed domains. Framer keeps yoursite.framer.app live as a staging domain, “also available when staging is disabled”.

For GA4, Framer has a Google Analytics Measurement ID field in Site Settings. Fathom needs data-spa="auto" on Framer, as above.

Squarespace

  1. Open the Code Injection panel and paste the tag into Header, which Squarespace adds to the <head> of every page. Save.
  2. Add your custom domain to allowed domains. Your built-in address, yoursite.squarespace.com, “won’t redirect to your custom domain”, and it is the address you see while logged in.
  3. Expect no data from checkout: Squarespace’s checkout pages do not support code.

Scripts also run in the logged-in editor preview, which is why Squarespace has a Disable Scripts in Preview button and why its GA guide warns that Google Analytics counts your own previews. GA4 itself goes under Developer tools → External API keys, and Squarespace’s cookie banner then handles Google’s consent mode.

Wix

  1. Go to Settings → Custom Code, under Development & integrations, and click + Add Custom Code.
  2. Paste the tag, choose All pages and Load code once, place it in Head, and click Apply.
  3. On the Code Type tab, pick the category your consent setup needs, as above.
  4. Add your custom domain to allowed domains.

Wix runs custom code only on a published site with a connected domain, never in the Editor or preview, and deletes the snippets if you assign a different domain. Google Analytics, Google Tag Manager and the Facebook and TikTok pixels “do not work through custom code”; connect them under Marketing Integrations.

Since December 2025 Wix locks objects such as fetch, URL and EventTarget against changes, which broke some older snippets. The invisit tracker only calls those and wraps history.pushState, which is not on Wix’s list; on the Wix site we tested it ran without a console error.

Carrd

Add an Embed element with Type set to Code and Style set to Hidden, Head, on Pro Standard or higher, and publish. Carrd adds Advanced Settings with element attributes on Pro Plus, which is where data-invisit-event would go.

Why can’t you proxy analytics through your own domain on a website builder?

A first-party proxy needs code on your domain that answers before the builder does, and no builder runs your server code. What some allow is a CDN in front of your custom domain, and only Webflow and Framer document one.

For invisit, a rewrite alone is not enough. The collector accepts a forwarded visitor address only from a proxy that signs its requests with your site’s ingest key, so a plain rewrite, such as a Framer Multi Site rule of type External, would make every visitor arrive with the address of Framer’s servers. Put invisit’s Cloudflare Worker on a route such as example.com/_i/*, then load /_i/invisit.js with data-collector="/_i" (proxy). We have not run that in front of a real Webflow or Framer site. Our proxy guide covers what a proxy recovers.

How to keep staging domains and editor previews out of your analytics

Allow only your real domain in your analytics tool, because three of the four builders serve a second address that runs your code, and two run it in the editor too:

Builder Second address that runs your code Editor preview runs it
Webflow yoursite.webflow.io Yes, in preview and comment modes
Framer yoursite.framer.app, even with staging off No
Squarespace yoursite.squarespace.com, which does not redirect Yes, while you are logged in
Wix None: custom code runs only on the connected domain No

In invisit, add your domain under Settings → Collection → Allowed domains; each entry covers its subdomains, up to 10 per site. We loaded our test page from a *.webflow.io host the site did not allow. The first page view left before the tracker had its settings and was refused with a 403. The tracker then logged that it was “not on this site’s allowed domains” and sent nothing more.

For your own browsing, open the live site once with #invisit-ignore at the end of the address, in each browser and on your phone (your own visits). Our internal traffic guide covers the same settings in GA4, Plausible, Fathom and others.

What we tested and what we could not

All tests ran on November 3, 2026, in Chrome for Testing 156 driven by Playwright 1.64.1, with invisit’s debug option on (the script sends nothing from an automated browser without it) and an ordinary Chrome user agent (the collector refuses headless ones).

Checklist before you trust the numbers