Install tracking by platform
Where the tracking snippet goes, and how to identify signups, on the platforms where it is not obvious. Pick yours.
Every platform uses the same snippet, carrying your own site key from Settings → Domains. The full explanation of what each step does - consent, cookie modes, cross-domain attribution, revenue matching - is in Set up website tracking.
<script async src="https://chartsy.fra1.digitaloceanspaces.com/production/static/track.js"
data-key="ch_pk_your_key_here"
data-api="https://dashboard.chartsy.app/api/attribution"></script>Webflow#
Tracks which channels bring visitors, and ties them to signups wherever those happen. A paid plan is required - custom code does not publish on the free Starter plan.
1. Add the tracking script
- Open your project, then Site settings → Custom code.
- Paste your snippet into the Head code box - not Footer.
- Save, then Publish. Custom code only goes live on publish.
2. Identify signups
A Webflow form. Select the form block, open the settings panel, and add a custom attribute named data-chartsy-signup with an empty value. The email field is picked up on submit.
A button that sends people to your app. The common SaaS case. Install the same snippet on the app too and register both domains in Chartsy - attribution follows the visitor across the link, subdomain or separate domain.
Webflow gotchas
- Changes need a publish. Saving custom code is not enough.
- Do not paste it into a single page's custom code unless you only want that page tracked.
- If you have enabled Webflow's cookie banner, it must not be set to block the script - the tag should always load.
Squarespace#
Tracks which channels bring visitors and ties them to signups. Business plan or higher - code injection is not available on Personal plans.
1. Add the tracking script
- Settings → Developer tools → Code injection.
- Paste your snippet into the Header box.
- Save.
2. Identify signups
Squarespace does not let you add custom attributes to form elements, so use a submit listener instead. Add it to the same Header injection, below the snippet:
<script>
document.addEventListener('submit', function (e) {
var email = e.target.querySelector('input[type="email"]');
if (email && email.value) window.chartsy.identify({ email: email.value });
}, true);
</script>That fires on any form with an email field. If you have several - a newsletter block and a contact form - narrow it with a block ID check, or only run it on the page that matters.
Squarespace gotchas
- Code injection does not run in the editor preview. Test on the published site.
- Password-protected and trial sites do not serve injected code reliably.
- Squarespace's cookie banner must not be configured to block the script.
Wix#
Tracks which channels bring visitors and ties them to signups. A Premium plan is required - custom code is not available on free Wix sites.
1. Add the tracking script
- Settings → Custom code (under Advanced in some dashboards).
- Add Custom Code, and paste your snippet.
- Set Add code to pages to All pages, and Place code in to Head.
- Under load timing choose Load code once - not "Load code on each new page".
- Apply.
2. Identify signups
Wix form elements cannot take custom attributes, so use the submit listener as a second code block with the same settings:
<script>
document.addEventListener('submit', function (e) {
var email = e.target.querySelector('input[type="email"]');
if (email && email.value) window.chartsy.identify({ email: email.value });
}, true);
</script>Wix members / account signup runs in Wix's own flow, which you cannot hook directly. Trigger identify from a Velo handler on member registration instead, or track the signup on your app domain if you have one.
"Load code once" matters
The other option re-runs the script on every in-site navigation, which double-counts. Wix sites are single-page apps underneath, so route changes do not reload the page - which is correct, since Chartsy counts one visit per session, not per page. Test on the published site, not the editor.
WordPress#
Tracks which channels bring visitors and ties them to signups.
1. Add the tracking script
With a header-scripts plugin (recommended). WPCode, Insert Headers and Footers, or similar - paste your snippet into the Header box. This route survives theme updates.
Editing the theme. Add it to header.php immediately before </head>, in a child theme - never the parent, which a theme update overwrites, taking your tracking with it.
In a plugin or functions.php:
add_action('wp_head', function () { ?>
<script async src="https://chartsy.fra1.digitaloceanspaces.com/production/static/track.js"
data-key="ch_pk_your_key_here"
data-api="https://dashboard.chartsy.app/api/attribution"></script>
<?php });2. Identify signups
A form plugin - Contact Form 7, Gravity Forms, WPForms, Fluent Forms. Each fires its own JavaScript event on successful submit. For Contact Form 7:
<script>
document.addEventListener('wpcf7mailsent', function (e) {
var field = e.detail.inputs.find(function (i) { return i.name.indexOf('email') !== -1; });
if (field && field.value) window.chartsy.identify({ email: field.value });
}, false);
</script>Other plugins use different event names - the shape is the same.
WooCommerce or a membership plugin. Fire it from the registration hook:
add_action('user_register', function ($user_id) {
$user = get_userdata($user_id);
add_action('wp_footer', function () use ($user) { ?>
<script>window.chartsy && window.chartsy.identify({
email: <?php echo json_encode($user->user_email); ?>
});</script>
<?php });
});WordPress gotchas
Optimisation plugins are the usual culprit
Chartsy reads its settings off its own <script> tag, so a "combine scripts", "defer JavaScript" or "minify and inline" feature that strips its attributes leaves it running with no key and measuring nothing. If tracking dies right after you enable one, exclude track.js from combining, deferring and inlining.
- Caching plugins may serve a cached page without the new script. Purge after installing.
- Do not edit the parent theme. Child theme or plugin.
- A consent plugin must not block the tag.
Google Tag Manager#
Use this when GTM is already on your site. If it is not, add the snippet directly - one fewer moving part.
1. Add the tracking script
- Tags → New → Tag Configuration → Custom HTML.
- Paste your snippet.
- Triggering → All Pages (Page View).
- Name it "Chartsy tracking", then Save and Submit to publish.
Leave "Support document.write" unchecked - the script does not need it.
2. Identify signups
If your signup form is a real form, add data-chartsy-signup to it in your site's HTML. That needs no GTM at all.
Otherwise make a second Custom HTML tag, firing on a completed-signup trigger:
<script>
window.chartsy && window.chartsy.identify({ email: {{DLV - signup_email}} });
</script>Where DLV - signup_email is a Data Layer Variable. Push it from your app:
dataLayer.push({ event: 'chartsy_signup', signup_email: 'person@example.com' });Then trigger the tag on the chartsy_signup custom event.
GTM gotchas
Consent Mode
Do not set the Chartsy tag to require analytics_storage. Blocking the tag means nothing is measured at all, rather than measured without cookies - Chartsy decides storage per visitor by itself.
- Publish, do not just save. Workspace changes do nothing until you Submit.
- The tag must fire on All Pages, not just the landing page, or you will miss the signup.
- Use Preview mode to confirm it fires before publishing.
Framer#
Tracks which channels bring visitors, and ties them to signups on your app.
1. Add the tracking script
- Site settings → General → Custom code.
- Paste your snippet into Start of
<head>tag. - Publish - custom code goes live on publish, not on save.
2. Identify signups
Framer sites are usually the marketing half of a SaaS, with signup on a separate app domain. Install the same snippet on the app, register both domains under Settings → Domains, and attribution follows the visitor across the link - subdomain or entirely different domain.
If you collect emails on the Framer site itself - a waitlist - add a second code block:
<script>
document.addEventListener('submit', function (e) {
var email = e.target.querySelector('input[type="email"]');
if (email && email.value) window.chartsy.identify({ email: email.value });
}, true);
</script>Framer gotchas
- Custom code only runs on the published site, not the editor or preview URLs.
- Framer routes client-side. Page changes do not reload the script - which is correct, since a visit is counted per session.
- Use a real link component for the button to your app. A click handler setting
window.locationwill not carry attribution across a separate root domain.
Check it worked#
Open your published site in a private window, then in Chartsy go to Settings → Domains and click View setup checklist on the site's row. "Add tracking snippet" flips to done as soon as the first visit lands - it is inferred from real traffic, so it confirms the snippet is firing, not just pasted.
If nothing arrives, view your page source and confirm the <script> tag is there with your real key. A blank or placeholder key is the most common cause.
Not your platform?
The snippet is plain JavaScript and works anywhere a <script> tag runs - see Set up website tracking. Still stuck: support@chartsy.app.


