Skip to main content
Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.

Tracking Google AdSense Clicks With jQuery And ColdFusion

By Ben Nadel on

While Google AdSense is in no way a driving force behind my blogging - I just love being a programmer - sometimes, it would be nice to know which pages on my site generated the most Google AdSense clicks. This might be something that I can find out from Google AdSense reporting or from Google Analytics; but, to be honest, I don't know all that much about those services and I wanted to see if there was a way this kind of information could be tracked in the domain of my understanding.

Because the content of a Google Ad lives inside of an IFrame under a different domain, I don't have the browser's permission to get in there and hijack any of the clicking events. As such, I think the best that we can do is "guesstimate" as to when an ad is clicked. But unfortunately, we can't perform that guesstimation with clicking since the click event won't bubble up from the AdSense IFrame. Luckily, however, we can track mouse movements over and out of the IFrame. Using this fact, and the window's blur() event, I think we can come up with something rather convincing.

In the following demo, we are going to use the mouseover and mouseout events to keep in an internal flag as to whether the user's cursor is over a Google AdSense unit. Then, when the window blurs (loses focus), we are going to see if the user's cursor is currently over a Google AdSense unit. If so, then we can assume to some degree that the blur event was triggered when the user clicked on the Google ad.

	<title>Tracking Google AdSense Clicks With jQuery And ColdFusion</title>
	<script type="text/javascript" src="jquery-1.3.2.min.js"></script>
	<script type="text/javascript">

		// When the DOM is ready to be interacted with, hook up
		// the DOM events for Google AdSense tracking.
		jQuery(function( $ ){

			// I am a flag that will determine if the user is
			// currently mousing over a Google AdSense.
			var isOverGoogleAd = false;

			// When a user mouses over a Google AdSense iFrame, we
			// want to track that activity. This way, when the
			// current window blurs, we can guesstimate as to
			// whether or not the window-blur was due to the user
			// clicking the Google ad.
			$( "iframe[ id *= google ]" )
						isOverGoogleAd = true;
						isOverGoogleAd = false;

			// Now that we are tracking the mouse movements over
			// the Google AdSense, let's track the window's blur
			// event to see if we can guesstimate the AdSesnse
			// usage.
			$( window ).blur(
					// Check to see if the user was over a Google
					// AdSense ad when the window was blurred.
					if (isOverGoogleAd){

						// Because the user was mousing over a
						// Google AdSense iFrame when the window
						// was blurred, it is reasonable to
						// estimate that the blurring is due to
						// the user clicking one of the ads.
							type: "post",
							url: "track.cfm",
							data: {
								adUrl: window.location.href

			// Focus the window by default.



		Tracking Google AdSense Clicks With jQuery And ColdFusion

		Google AdSense elements have to be on the same page as the
		primary content of the page. As such, we will mix in the
		AdSense SCRIPT tags within this content.

	<!--- Google adsense. --->
	<script type="text/javascript">
		google_ad_client = "pub-1768217795487021";
		google_ad_width = 468;
		google_ad_height = 60;
		google_ad_format = "468x60_as";
		google_ad_type = "text_image";

		Here is some more content for the page. To fill up some
		space, I'll just talk about some random stuff that is
		not that interesting.


When we have determined that the blur() event was triggered by a Google ad click, we make a jQuery AJAX request to the server, sending the current location of the browser as the request data. This request is then received by a simple ColdFusion page that, for this demo, appends the URL to a given file:

	I am the location of the browser when a Google AdSense ad
	was clicked (theoretically).
<cfparam name="form.adUrl" type="string" default="" />

<!--- Make sure that the URL has a valid length. --->
<cfif len( form.adUrl )>

		Simply append the URL to the tracking file for this demo.
		In reality, you would probably insert this into a database
		or an email.
		file="#expandPath( './google_ad_clicks.txt' )#"
		output="#dateFormat( now(), 'mm/dd/yy' )# - #form.adUrl#"


<!--- Retur a response just so the AJAX can finish ASAP. --->
<cfcontent type="text/plain" /><cfabort />

This is simple, but I think the theory is sound. Like I said above, I don't really know Google AdSense or Google Analytics all that well; so, if this kind of information is easily obtainable form those services, please let me know.

Reader Comments


I think I see a couple areas this may fail

first case

What if a user uses ALT+TAB while the cursor is over the GoogleAd

second case

What if the user opens the link in a new tab? which I don't think blurs the window at the time of the click


I had the same suspicion regarding the ALT-TAB. The ALT-TAB does seem to trigger the event as a false-positive. The new-window, CTRL+CLICK, however, triggers it correctly.

This is, of course, just an estimation as to when the user clicks on the ad. One thing I was thinking about, which was a bit beyond the scope was to add a "complete" call back for the ad such that, let's say, 7 seconds after the AJAX call returns, it launches another request to erase the previous tracking.

The idea there being that if the page still existed 7 seconds later, chances are the page is not loading another URL. Of course, this would return a false-negative if the use opened the ad in the other window.

So again, just an educated guess as to when this stuff is clicked, certainly not a dead-on accurate approach.


did the CTRL+Click open a new window or new tab, I know when it is a new tab the tab opens in the background; However, when it is a new window, the window is in the foreground


Thanks for clarifying, wasn't sure with the way you worded it before.

Interesting that the blur() even is triggered there. I wonder if it has to do with the internal workings of firefox


Oops, I think I got myself confused :) I believe earlier I called teh CTRL+CLICK a false positive because it didn't close the current window. But, I forgot that closing the window was not the main motive - tracking the clicks was.

In summary, what I saw:

CTRL+CLICK (new tab) - successfully tracked.

ALT+TAB - false-positive for click.

I am not sure if someone above answered this but you can track this when you marry Google Analytics and Google AdSense together. It works great at tracking which pages are preforming the best.



Once you join your AdSense and Analytics accounts, I am not sure that using this technique would offer any benefit?


I don't think so, but I still enjoyed your video on the topic.

If I remember right they allowed us to join the accounts earlier this year. It has been a great thing because now I know which pages and keywords bring in the most $ and I can adjust for that.



It's definitely very cool; I only found about the linking of AdSense and Analytics in @Rudi's comments above. So, it's very new to me; so far, it seems very cool in my Analytics.


I have a hobby solar site and the info I get from knowing which pages are performing the best has increased my monthly revenue by a lot - perhaps 20%.


Sounds awesome. I know what you did to increase the revenue is probably something you don't care to share; but, if you have any tidbits of insight, I'm sure we'd all love to hear.


Sure I would love to share. I owe you at least that since you have answered some of my coding questions in the past.

Here is one easy tip, check out my site and notice what I did on the home page, I placed all my top producing $ pages under the heading "Popular Posts", and doing that increase the traffic to those pages and generated more revenue for me. I wouldn't have known which posts made the most $ without the joined accounts.

Again this is just my hobby site and I have used other methods on my main sites like knowing which pages to pass the most link juice to for internal and external links. More links to a page usually means more traffic to a page - which means more $.

Also it is about looking at themes, for instance anytime I write a post on my Solar site that has the theme of DIY I usually get the highest CTR on those pages. Also since you are getting into video, post your video on YouTube and check out how long people actually watch it and that lets you know how engaged they are with that theme.


Really Nice video with useful explanation. But i have some questions in my mind..

1. The technique will pass Google Terms and conditions?

2. Where you are hosted the above video? Or its self hosted? If self hosted, Which plugin you are used to embed video in your blog?

3. It seems you are using Jing for your video demo. Which video format you are used to record this video.

Video buffers faster than ever :)


Ahh, very nice - driving as much traffic to the top earning posts. That makes a lot of sense. It will be interesting to see what the Analytics tells me. Looking forward to getting a bit more data in there.


Yeah, I am using JING and I self-host the videos since they are quite small. You can hook JING directly into FTP.

Hmmm, is there not away to see if someone is leaving your site? -- You know like those annoying little alert boxes that come up on sales page ( Are you sure you want to leave this AMAzING offer! ) you know something like that? But have it tied into the iframe?



You can fire an onUnload() event on the window; however, that doesn't happen until the URL *actually* changes; this might be a few second delay between when they click and when they navigate away. In this time, I didn't want the user to mouse-away from the IFrame (and cancel the tracking).

I'd like to ask the same question Selvam asked (but not answered):

Is this technology allowed by Google's Terms and Conditions?


I don't see how it could be against policy.


Hmm, interesting question. I'm trying to think back if I tried that or not. The only problem might be that the click would be trapped by the IFRAME document. The question becomes - can an event bubble up across documents (from IFRAME to parent page).

I am not sure if it can.

Hi all,

Very nice conversation here.
I found your post on a search for more info about how to consider a click on AdSense as an event in Analytics.

As Dave said it, the AdSense/Analytics linking is really useful and gives you more in-depth data about how your pages are monetized.

But in my case, it must be more specific.
I have loads of dynamic generated pages (thousands !) and different types of pages.

So I used the Event Tracking code to categorized the different types, and labeled different page sections by zones.

That way, I know exactly what are the performing zones, for each actions, in my different page types. But all this is for my external links affiliate program.

Recently, I focused on AdSense and how it could give me more $. This is the reason why it would be really interesting for me to know how to track AdSense clicks as events.

If anyone can help me here, I will be very grateful !

I was recently searching for information regarding AdSense Mobile and jQTouch and came across this post.

I thought I'd share my tracking snippet with you. I'm tracking click-thru activity using encrypted IDs that are added to all links using the "rel" tag. The encrypted data contains the ID of the resource being tracked and a code representing the type of resource being clicked (website, youtube, twitter, gallery, rss, etc.)

$('a[rel*=track-]').bind('click', function() {$.post('/track.cfm', {ID:this.rel}); return true;});

This has enabled us to easily generate daily statistics based on click activity. I can also filter the administrators and account holders from the statistics by not suppressing this script from being outputted (or adding logic to track.cfm.)


Do you ever run into problems with the asynchronous nature of the $.post() method? After I posed this, I have talked to some people that claimed that you actually need to force the sync nature of the request in order to make this dependable.

url: "api url",
async: false

This seems like the *last* thing you want to do on a mobile device (like the request needs to be made any slower).

From what you are saying, though, it sounds like you are having fine success without single-threading the requests.

I think you may be right right regarding switching to ajax() and using the async feature. I enabled it this morning after your feedback. Thanks!


I'm excited to hear if you notice any differences. I'd be sure to check it on mobile to see if there is a noticeable performance hit. Statistics are probably not worth it at some costs. Keep us updated.

This is clever, I like it. I'll probably use this event, but for tracking Facebook like box clicks. As far as I know, there is no native way in Facebook to track the origins of a like box click, so this fills in that missing gap nicely.

As you admit, it's just a guesstimate, but it's nice to be able to even provide that when clients ask if the apps they build us are translating to additional FB fans.


Awesome my man. If/when you integrate it with the Like widget, I think we'd all love to hear how it goes.

This is not working for me. Tried with Opera and Firefox. Only if using ALT+TAB to loose window focus while the mouse is over the hotspot the if (isOverGoogleAd) gets triggered. Seems like when window looses focus (blur) by going to a URL the script itself is unloaded from the page to.


Perhaps the unload is happening too fast and the ASYNC nature of the tracking request is not happening in time. You can override the nature of the AJAX request in jQuery and set it to SYNC. I believe I have heard that this will solve the problem you are having (but I have not tested it personally).

First of all, nice script. I added a little extra functionality to track the adSlot, width and height for more granularity in tracking.

  • $('iframe[id *= google]"').mouseover(
  • // save the current frame url
  • function(){isOverGoogleAd = this.src;}
  • ).mouseout(
  • function(){isOverGoogleAd = undefined;}
  • );


  • var tokens = isOverGoogleAd.split('?')[1].split('&');
  • function getToken(name) {
  • var result = false;
  • $(tokens).each(function(i, item) {
  • var tmp = item.split('=');
  • if(tmp[0] == name) {
  • result = tmp[1];
  • }
  • });
  • return result;
  • }
  • $.post(ajax_url, {
  • ...
  • slotname: getToken('slotname'),
  • w: getToken('w'),
  • h: getToken('h'),
  • ...

Thanks for the code example. I know it is quite a while ago since you wrote this, but there are two questions on my mind and maybe somebody can help:

1. Why should I use the focus() command. Is it required? It seems to work without, can't I just assume that it has focus and if it does not it will probably have a good reason?

2. Right now it only tracks clicks once, which is fairly reasonable given that another site is loaded. But I made the experience that some of the modern browsers do not reprocess the whole javascript when users use the back button (and then click on another ad). This would also apply to the situtation where Adsense opens in a new window.

really tough to understand and implement for non-techy guys like me..But will try as tracking ad sense clicks is very important.

I was curious about implementing this to work with Adwords conversion tracking. Essentially, you could know when anyone clicks and adsense unit on your site.

Adwords makes it somewhat easy by allowing you to fire a function from the "onclick" event, but to implement that same functionality with this script. I'm completely useless at javascript though.

Would I simply replace your


With the Adwords function:



Thanks for any help!

I sounded dumb in that last post.. I meant you would be able to track any Adsense unit using your function, plus track any *other* manually placed Ad units (such as to affiliate products) using the built in Adwords "onclick" call with similar consistency, such as comparing whether you get more revenue from affiliate or Adsense on your site.

Hello Ben,

This is my first visit to your site, it is very nice. I don't remember what I was searching for when finding your site but enjoyed the info on capturing potential ad-clicks for Google Ad-Sense.

I would like to try your solution on my main site, a programming and Adsense Tips Blog and a few others for which I am not getting poor CTR on ads. Some of my sites have an Adsense RPM under a dollar and and it makes me wonder if the Adsense code isn't working properly on some sites.

I am happy to share thoughts with anyone on Adsense and do a lot of it on my main site. You can email me with questions too, maybe we can help each other. In general technical sites are not the best for making money you are better off with other niches, try to get your RPM as high as possible, like $10 or higher for easier money making ability.

I have been doing blogging and Adsense since around 2010 and the income growth has been slow and steady but always going in the right direction. Last month was the high for the year at $62.xx. The first year I averaged a penny a day, then ten cents a day. It took at least until the second year before I averaged over a dollar a day and most of 2013 has been averaging around $2 per day. I do no advertising. I am trying to hit $150 per month in Adsense revenue each month during 2014 and ultimately some day $150 per day. :)


This is a topic I was looking for. My sponsor asked for the number of clicks generated from my website. I use WordPress. However, none of clicks recorded for the sponsor. Although I try to click on it my self several times, still no record in Wordpress. It also happens with Adsense. WordPress can not record clicks on Adsense.

My sponsor have code using object like this:

<object classid = 'clsid: D27CDB6E-AE6D-11CF-96B8-444553540000' codebase = 'http: //,0,0,0' id = 'Notepad 2 Indonesian (Revision) "width =" 728 "height = '90'> <param name = 'movie' value=''> <param name = "quality" value = "high"> <param name = 'wmode' value = 'transparent'> <embed name = 'name' src='' quality = "high" wmode = "transparent" width = "728" height = '90 'type =' application / x-shockwave-flash 'pluginspage =' http: // cgi? P1_Prod_Version = ShockwaveFlash '> </ embed> </ object>