How to track your website link clicks using a single HTML attribute?

Let’s say you have created a web app.

You have lots of hyperlinks in your app, either to your own web pages or to external resources.

You want to track those links:

Who clicked it?

When was it clicked?

How many times a particular link was clicked?

Until HTML5, you had to write javascript code to do this , but since HTML5 you can do this very easily by just including one attribute: the “ping” attribute in hyperlink tags.

For example , in the below code:

<a href="https://google.com" ping="http://localhost:8081/track">Click here</a>

user is directed to google.com on clicking the link ‘Click here’.

Once they do that , the attribute ping makes a ping to the URL assigned to it , in this case localhost:8081/track.

This is a simple POST request with the request string “PING”.

You can get who clicked the link by getting the attribute value “ping-from” from the request HEADER.

You can get which link was clicked by getting the attribute value “ping-to” from the request HEADER.

Here are the steps :

STEP1 : Include ping attribute (with the target URL which is used for tracking) for all the links that you want to track in your HTML pages

STEP2 : At the server side , write a POST REST API for the corresponding URL

STEP3 : Extract the header “ping-from” – this gives the source of the click

STEP4: Extract the header “ping-to” – this gives the link which is clicked

STEP5: Use both the values got from step 3 and step 4 to track the number of hits and their sources and destinations by storing them in a database

STEP1: Include ping attribute.

Here is a sample HTML file which I created to test this:

<html>

<body>

	<a href="https://google.com" ping="http://localhost:8081/track">Click here</a>
	
</body>

</html>

The URL given for ping attribute is the URL of the REST API used to track the clicks to google.com (which is referred to in href attribute).

I deployed this file to tomcat server by creating a folder pingdemo under webapps folder of tomcat and named it as “index.html”. The html page then got served from the url http://localhost:8080/pingdemo

STEP2: Write the service to track the clicks:

I used Spring Boot for writing the server side REST API. Here is the code:

package com.ping.track;

import java.util.Map;

import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@org.springframework.web.bind.annotation.RestController
public class RestController {

	@RequestMapping(method = RequestMethod.POST, value = "/track")
	@CrossOrigin
	public void track(@RequestBody String request, @RequestHeader HttpHeaders header) {

	
		
	}
}

It is just a POST REST API accepting RequestBody and RequestHeader from the input API requests. RequestBody just contains the string “PING” . The source and destination of the clicks can be obtained from the RequestHeader.

I served the app from port number 8081 by configuring it in application.properties:

application.properties:

server.port=8081

The server side tracker service got served at :

http://localhost:8081/track

STEPS 3 & 4: Extract source and destination of clicks from input request header

Extract the source from “ping-from” header attribute. This represents where the hit came from.

Extract the destination from “ping-to” header attribute. This represents which link was clicked.

Here is the updated code:

package com.ping.track;

import java.util.Map;

import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@org.springframework.web.bind.annotation.RestController
public class RestController {

	@RequestMapping(method = RequestMethod.POST, value = "/track")
	@CrossOrigin
	public void track(@RequestBody String request, @RequestHeader HttpHeaders header) {

	
		System.out.println("Source of the click: "+header.getFirst("ping-from"));
		System.out.println("Destination of the click: " + header.getFirst("ping-to"));
		
		System.out.println("Request value: "+request);
		
		Map<String,String> values = header.toSingleValueMap();
		
		System.out.println(values);
	}
}

I am printing the source of the click , the destination , the request and all the values present in the header.

Here is the output:

Source of the click: http://localhost:8080/pingdemo/
Destination of the click: https://google.com/
Request value: PING
{host=localhost:8081, connection=keep-alive, content-length=5, ping-from=http://localhost:8080/pingdemo/, cache-control=max-age=0, user-agent=Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Mobile Safari/537.36, ping-to=https://google.com/, content-type=text/ping, accept=/, origin=http://localhost:8080, sec-fetch-site=same-site, sec-fetch-mode=no-cors, sec-fetch-dest=empty, accept-encoding=gzip, deflate, br, accept-language=en-US,en;q=0.9}

As expected , the click came from the html page deployed at localhost:8080.

The destination of the click was google.com.

The request is just the word PING.

The header contains the source , the destination , the host where the tracking service is deployed , the browser details from which the click happened (user-agent) etc.

The html page :

After it is clicked there are two http requests as seen in the Network tab, one to localhost:8081/track and the other one to google.com:

Here is the request header and request payload of /track call as seen in the browser:

STEP 5: Track the clicks.

You can track the clicks by storing the source URL & destination URL in a database table .You can create a counter column which stores the count of hits for the source and destination URL combination. Whenever the URL is hit you can increase the counter. You can also store the time in which the request came to the tracking service which represents the time of the click.

That’s it.

Tracking the clicks from your web app became much easier with the “ping” attribute introduced in HTML5.

This attribute is looked down by few as it becomes easier for advertisers to track the clicks of users. But anyways they already track it through javascript code. Most of the modern browsers support this attribute except Firefox which supports it but disables it by default. You need to manually enable it in your browser for this attribute to work.

The details of browser support for this feature can be seen here:

https://caniuse.com/ping

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s