lytics

Guide

Track button clicks and form submissions with lytics

Count how many visitors click your signup link and how many submit your waitlist form. You install the lytics snippet once, give the link and the form names that will not change, and add two tags from the dashboard. After that, new tags reach the site without another deploy.

Checked against the current lytics tracker and Tags form: the sample page below, with the two tags, sends exactly the events listed in step 6. A tag sends an event name and nothing else — never what was typed into a form, an email address or any other personal detail.

How tags work

The lytics snippet loads a tracking script from lytics on every page. That script counts pageviews, and it also carries the app's tags: rules of the form when this happens, send this event. A tag is a CSS selector or a path and an event name — there is no way to add code to your page from lytics.

1. Create an account and an app

Create an account, or sign in. You arrive on Your apps. Under Add an app:

FieldWhat to enter
NameAnything you will recognise, e.g. Example landing page.
DomainsEvery hostname the site is served from, comma-separated — for the sample, example.com, www.example.com. www.example.com and example.com are different hosts; *.example.com covers both and every subdomain. Events from any other host are dropped. Testing on your machine? Add localhost while you do.

Press Add. lytics opens the new app's page with Set up this app at the top. Domains can be changed later under Settings on that page.

Create an account and add an app

2. Install the snippet once

Copy the snippet from the app's setup — or its Install section, which shows the same one — into the <head> your pages share: the layout or template every page uses. It looks like this, with your app's own key where this one says lyt_REPLACE_WITH_YOUR_SITE_KEY:

<script>window.lytics=window.lytics||function(){(lytics.q=lytics.q||[]).push(arguments)};</script>
<script defer src="https://lytics.lp-data.cloud/api/t/lyt_REPLACE_WITH_YOUR_SITE_KEY.js"></script>

Copy it from your app rather than from this page: the key is what sends the events to that app. Deploy, open the site, and press Check for pageview in the setup. Carry on once it confirms a pageview — if pageviews do not arrive, tag events will not either, and the setup lists what to check. On an Astro site, see Add analytics to an Astro site first.

3. Give the link and the form stable names

The sample is the landing page of a fictional product: a signup link in the header, another in the page, and a waitlist form. The snippet is in its head, and the elements to track carry names made for tracking:

Sample landing page
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>Example — plan your week</title>
  <!-- The lytics snippet, from your app's Install section. Once, in the
       shared <head> every page uses. Tags added later need no new deploy. -->
  <script>window.lytics=window.lytics||function(){(lytics.q=lytics.q||[]).push(arguments)};</script>
  <script defer src="https://lytics.lp-data.cloud/api/t/lyt_REPLACE_WITH_YOUR_SITE_KEY.js"></script>
</head>
<body>
  <header>
    <a href="/">Example</a>
    <a href="/signup" data-analytics="signup-link">Start free</a>
  </header>

  <main>
    <h1>Plan your week in five minutes</h1>
    <p>A fictional product, for this guide.</p>
    <a href="/signup" data-analytics="signup-link">
      <span>Create your free account</span>
    </a>

    <h2>Not ready yet?</h2>
    <form id="waitlist-form" action="/waitlist" method="post">
      <label for="waitlist-email">Email</label>
      <input id="waitlist-email" name="email" type="email" required />
      <button type="submit">Join the waitlist</button>
    </form>
  </main>
</body>
</html>

4. Add the signup-click tag

On the app's page, go to Tags and fill in the form:

FieldValue
WhenAn element is clicked
Matching[data-analytics="signup-link"]
On paths startingempty — every page
Send the eventsignup_clicked

Press Add tag; it appears in the list as Click on [data-analytics="signup-link"], sends signup_clicked. A click counts when it lands on a matching element or anything inside it, so a click on the <span> inside the second link counts too. Enter on a focused link is a click as well.

5. Add the form-submit tag

Add a second tag:

FieldValue
WhenA form is submitted
Matching#waitlist-form
On paths startingempty — every page
Send the eventwaitlist_submitted

A submit tag matches the <form> element, not its button: #waitlist-form, not #waitlist-form button. The event is sent when the browser submits the form — by the button or the Enter key — after the browser's own checks such as required pass, and before your server answers. So it counts submissions, not successful signups; for those, see Troubleshooting.

6. Check the events

Wait up to five minutes, or open the site in a new private window so it fetches the script with the new tags. Then click and submit. With the two tags, the sample sends:

The visitorEvents sent
Opens the home page, /pageview
Clicks “Start free” in the header — or the words inside “Create your free account”signup_clicked
Fills in an email and presses “Join the waitlist”waitlist_submitted
Presses “Join the waitlist” with the email field emptynone — the browser stops the form
Opens /pricing and clicks “Start free” therepageview, signup_clicked, signup_clicked_pricing

The last row assumes the optional /pricing tag from Path prefixes; without it, only pageview and signup_clicked.

Where to look on the app's page:

Each event is stored with its name, the page's path (never its query string), the time, the kind of device and, if your app identifies signed-in users, their id. Not the text of the link, not the form's fields.

The optional path prefix

On paths starting limits a tag to pages whose path begins with what you type. Empty means every page, which is what both tags above use. Say the fictional site also has a pricing page with the same link:

<!-- /pricing — same <head>, same snippet -->
<a href="/signup" data-analytics="signup-link">Start free</a>

To know how many signup clicks come from pricing, add a third tag:

FieldValue
WhenAn element is clicked
Matching[data-analytics="signup-link"]
On paths starting/pricing
Send the eventsignup_clicked_pricing

Every tag that matches a click sends its event, so a click on pricing sends both signup_clicked and signup_clicked_pricing: the first stays the site-wide total, the second is the pricing share. The prefix is compared as plain text from the start of the path — case matters, and hostnames and query strings play no part:

PrefixMatchesDoes not match
/pricing/pricing, /pricing/teams, /pricing-2025/, /en/pricing
/pricing//pricing/teams/pricing
/every page — the same as leaving it emptynothing

On a single-page app, the path is checked when the click happens, so a tag follows client-side navigation.

Choosing event names

Troubleshooting

SymptomWhat to check
Pageviews arrive, but a new tag sends nothing.Tags travel inside the tracking script, which browsers keep for up to five minutes. Wait, or open the page in a new private window, which fetches the script again.
Nothing arrives at all, pageviews included.The snippet is not installed on that page, or the page's host is not one of the app's domains. Go back to the app's setup until it confirms a pageview — tags cannot work before that does.
The submit tag never fires, though the click tag does.A submit tag's selector has to match the <form> element itself (or something around it), not its button. #waitlist-form button matches nothing on submit; #waitlist-form does.
The form is sent, but no submit event arrives.The form is being sent by a script calling form.submit(), which browsers send without a submit event. form.requestSubmit(), a submit button or the Enter key all fire one. If the form is not a <form> at all, tag a click on its button instead.
More submit events than real signups.The event is sent as the browser submits the form — after its own checks, such as required, but before the server or the page's script has accepted it. To count signups that succeeded, tag a view of the thank-you page (A page is viewed), or send the event from the app with lytics('event', …).
The dashboard says a selector or a path is not allowed.A selector can be up to 200 characters, without <, >, { or }. A path has to start with / and contain no spaces. An event name is letters, digits, _ . : - $ and spaces, up to 64; pageview is taken.

Events from automated and headless browsers are dropped as bots, so test in an ordinary browser window. An ad or tracking blocker can stop the script or its requests as well.

Next