Last Updated: February 25, 2016
· mariomc

No JS Click Tracking


Being able to track how a user interacts with your application is important for you to develop a smooth experience.
Being accessible to all environments is also important.

However, this led to a question: How do you measure interaction of a user that hasn't got JS enabled?


All the following techniques revolve around this single browser optimization:
it won't request an image used in CSS if it's state is not currently applicable

Using HTML elements that can maintain/change state (anchors, inputs, buttons), you can infer an interaction has occurred.

Please keep this in mind: Due to the way browsers cache the resources, each interaction will only be tracked once per session . Which means, you'll only be able to know if an action has been triggered in a certain session, not how many times it has happened.

How does it work?

Take a look at this JS Fiddle for an idea of how it works.


  • Have your own tracking gif. If you have a Google Analytics account, you could use the GA tracking gif with the proper parameters. For these examples we use a placeholder image.
  • If you're already tracking using JS, mark your page with the presence or absence of JS. This is usually done with a 'js' or 'no-js' class on the HTML element. Either use Modernizr or set a 'no-js' class and remove it with JS. Restrict the below selector to '.no-js' if that's the case.

Technique #1 ( anchor + hover + active )

    content: url(;
<a href="" target="_blank">Click me!</a>


  • Easy to use
  • Can be used to track outbound links


  • May trigger false positives as you can trigger a mousedown without a click (right click, mousedown on element and mouseup outside of element).
  • Doesn't work on keyboard navigation.

Technique #2 ( button + focus + active )

    content: url(;
<button>Click me!</button>


  • Works with keyboard navigation


  • May trigger false positives as you can trigger a mousedown without a click (right click, mousedown on element and mouseup outside of element)

Technique #3 ( radio button )

input:checked:after {
    content: url(;
<input id="kpi3" type="radio" value="" />
<label for="kpi3">Click me</label>


  • Works with keyboard navigation
  • No false positives for the right click


  • Hard to use
  • Very narrow

Variant #4 ( multiple KPI )

You can use CSS3 multiple background image to pick several endpoints at once. Note that this will reduce the browser compatibility.

    content: '';
   background-image: url(, url(;

<button>Multiple Images!</button>


What can you track

  • Pageviews ( using the image on the body )
  • Clicks on anchors
  • Clicks on buttons
  • Active links (through the use of :target)
  • Active form elements
  • Some device metrics ( through the creative use of media-queries )

What you can't track

  • How many clicks occurred
  • When an element became visible on the viewport
  • User info ( IP, location, referer, user agent, etc ). Although you could infer this if you control your tracking bug/gif and if you could dynamically generate the CSS server side.


The usability is marginal, but when you have rich CSS only components like a CSS3 slider, CSS3 Tabs or even a CSS Modal, why not have a CSS only way to track interaction as well?

Use it wisely and have fun tracking!

1 Response
Add your response

Nice write up. Very interesting stuff.

over 1 year ago ·