In: , , , ,
On: 2004 / 09 / 17
Shorter URL for this post:

You have a blog. You have stats telling you how many people read it. You post links. But do you have something telling you how many people click on your links ?

Here is it : I'm releasing my latest plugin, Click Counter. Basically, it adds a click counter to links in your posts, as in these examples :
I love WordPress, WordPress and WordPress.
Click on one link and reload the page (hit counter displayed on mouseover link title, in plain text, or both)

Less basically, it comes with a real bunch of options you'll probably never need to tweak, but I wanted to do something as flexible and usable as I could.

Current version : 1.02

Note : you may find sometimes this plugin disabled here on my own server, when I'm tweaking a few things. The plugin is fully functionnal anyway, download it :-)

Note: The plugin is rather well commented, advanced users can probably directly download, edit and run. I'd suggest reading the "How it works" and "Tips & Tricks" sections anyway.

Set up the MySQL table

You need a new table in your WordPress database, named wp_linkclicks (you can modify the name, be sure then to edit the beginning of the plugin properly) Create this table with the following query :

  1. CREATE TABLE `wp_linkclicks` (
  3.  `link_url` TEXT NOT NULL ,
  4.  `link_clicks` INT NOT NULL ,
  5.  `link_date` DATETIME NOT NULL ,
  6.  `link_title` TEXT NOT NULL ,
  7.  UNIQUE (
  8.   `link_id`
  9.  )
  10. );

Newbie tips : first, install PHPMyAdmin on your website. This is a great interface for anything you can do with MySQL databases. Once it's done, look for the "SQL" link in the menu : click, and paste in the textbox the above code. It will set up the required table for you.


Download the plugin :
Extract and upload to your blog, preserving directory structure if any.
Note: download counter here and stats on may differ and reflect the number of downloads before this plugin was hosted on the plugin directory

The archive contains the tracker file, go.php : put this file in your blog root. If for some reason you want to modify the tracker file name, be sure to properly edit the beginning of the plugin script as well.

Use the plugin

In its default configuration, the plugin needs nothing more. Get back to your blog and post as usual. It will silently add trackers to links in your posts and links in commenters' posts.

A small warning : adding a counter to a link "costs" one SQL query. If you are hosted on a slow server, or if you are teh ultimate linkblogger with 200 external links posted in your frontpage à la Metafilter, you might slightly overload your SQL server :) If this is your case, read by the end of this article the Tips & Tricks, I'll explain how to add a "silent tracker with no SQL query".

Another small warning : the plugin works with proper xhtml syntax, that is href="url" or class="myclass" (quotes), not href=url or class=myclass (no quotes)

How it works

Don't change anything to your posting habits, the plugin is the "install & forget" type.

When your WordPress will print a post with a link, the plugin replaces every link target and title. For example :

  1. <a href="">link</a>


  1. <a href="yourblog/go.php?"
  2.   title="XX clicks">link</a>

The number of clicks in the title value will be added to an existing title if specified : title="this is a cool link (XX clicks)"

When someone clicks on this modified link, it will add or update the following values to the table you've created earlier :

  • link_id: the link id, which is more or less useless
  • link_url : the url, "" in the above example
  • link_clicks : how many people clicked on it
  • link_date : the date of the first click on it (not the date you posted it)
  • link_title : the title of the remote page, if exists, as defined by its title html tag

Unless stated otherwise, only external links will have a counter added, because it's pointless to track how many people click on your pages. There are stats plugins for this :)
So, if you want to add a counter to an internal file, put a absolute path in the link html : href="http://site/blog/file" instead of href="file"

Template Tags

I've written two "template tags" you can add to your pages

  • wp_ozh_click_topclicks($limit, $trim , $pattern) : displays your most clicked links
  • wp_ozh_click_comment_author_link() : a replacer for comment_author_link() in wp-comments.php, if you want to add a counter to your commenters' website when specified.

As you can see, the first one, wp_ozh_click_topclicks, has 3 optionnal arguments :

  • $limit : how many links you want to display. Default value is 5, and can be modified in the plugin.
  • $trim : maximum length for displayed links title. Setting this for example at 5 will convert "WordPress Home" to "Wordp…". Default value is 15, and can be modified in the plugin.
  • $pattern : html code used to display the list. See right below.

The pattern parameter is an html string with template tags. The default value, as defined in the plugin, is :

  1. <li>
  2.   <a href="%%link_url%%" title="%%link_title%%">%%link_title_trim%%</a>: %%link_clicks%%
  3. </li>

Tags are enclosed in between "%%" and can be :

  • link_id: the link id number in the sql database, I don't see why you would use this one :)
  • link_url : the link url, obviously.
  • link_clicks : the number of clicks the link has received so far
  • link_date : date of first click (more or less useless too, I admit)
  • link_title : remote page title
  • link_title_trim : shortened value of link_title, trimmed to the value of $trim as defined previously.

If the target page has no title, and is html content, the title will be replaced by the url itself. In this case, %%link_title%% will output the url, shortened by its trailing slash and leading http://www. if applicable.

It the page has no title because it's not an html document ( for example), it will be replaced by the document name (

Optionnal configuration tweaking

Now, I'll go through all the variables and their default values you can modify and edit at the beginning of the script. For the interested only, most users don't need so much tweaking and are probably bored of reading this page :)
Note : as usual, I've named the plugin file, functions and vars with a beginning "wp_ozh_click" to prevent any nuclear world war.

Core variables :

$wp_ozh_click['table'] = 'wp_linkclicks'
Name of the table where stats will be stored

$wp_ozh_click['file'] = get_settings('siteurl') . "/go.php"
Name and location of the tracker file

Basic features :

$wp_ozh_click['track_all_links'] = 1
Value can be 1 or 0
If set to 1, every link will have a tracker. Just post as usual.
If set to 0, you will have to specify when you want to add a tracker, with the following code :

  1. <a href="" count="1">link</a>

The value countwill be removed at processing time, so output will be valid html.
The value of count can be : 1, title, inline, or a mix.

  • count = "1" : number of hits will be added to link according to the default behaviour as defined in the script (see below)
  • count = "title" : number of hits added in link title : <a href="" title="69 hits">link</a>
  • count = "inline" : number of hits added in plain text, after the link : <a href="" >link</a> (69 hits)
  • count="title inline" : both : <a href="" title="69 hits">link</a> (69 hits)

$wp_ozh_click['in_title'] = 1
Value can be 1 or 0
Default behaviour for displaying counter (according to $wp_ozh_click['track_all_links'] or to count value in the link html). If set to one, display hit number in link title.

$wp_ozh_click['in_plain'] = 0
Value can be 1 or 0
Default behaviour for displaying counter (according to $wp_ozh_click['track_all_links'] or to count value in the link html). If set to one, display hit number in plain text after the link.

$wp_ozh_click['0click'] = 'No click'
Default text for zero click

$wp_ozh_click['1click'] = 'One hit'
Default text for one click

$wp_ozh_click['clicks'] = '%% hits'
Default text for several clicks, where %% will be replaced by a number

$wp_ozh_click['method'] = 2
Value can be 1, 2 or 3.
There are 3 ways to modify the link html to add the tracker. Each has advantages and drawbacks, but all validate any Doctype up to XHTML 1.1. If you want things to remain simple, just skip this setting and leave its default value
Depending on the chosen method, <a href=""> will become :

  • Method 1:
    <a href="" onclick="window.location='/go.php?'; return false">
    Cool : status bar shows real link without further trick.
    Less cool : doesnt work with "open link in new window"
  • Method 2:
    <a href="/yourblog/go.php?">
    Cool : works with "open in new window" and doesn't require Javascript enabled
    Less cool : shows ugly link "/blog/go.php?" in status bar
  • Method 3:
    like method 2 but also modifies status bar to hide the ugly and sometimes annoying "" part with onmouseover="javascript:window.status=''; return false"
    Cool : status bar shows real link.
    Less cool : adds a few bytes of html
  • I'd suggest you use preferably method 2, or at least method 3. Method 1 is really less accurate since it doesn't keep track of links opened in a new window

$wp_ozh_click['do_posts'] = 1
Value can be 1 or 0 :
Do you want to add a counter to links in your posts ?

$wp_ozh_click['do_comments'] = 1
Value can be 1 or 0 :
Do you want to add a counter to links in your commenters comments ?

Now onto the link title features :

$wp_ozh_click['get_title'] = 0
Value can be 1 or 0.
Get remote page title the first time a user clicks a link to store it along with hits in the table. This will slow down the first clicker, by 1 or 2 seconds maximum, time for your website to retrieve the distant page and parse it.
Note : mostly untested feature. It uses fopen(), check your host has enabled this (if not, the plugin will work anyway, and title will simply be empty)

$wp_ozh_click['get_title_forcerefresh'] = 50
Value is an integer.
Refresh remote page title every XX clicks. Set to 0 if you don't want to use this feature. If you chose to use it, the higher traffic – then clicks – you get, the higher you should set this. Examples : 50 for Joe's blog, 3000 for Slashdottish blog.
To be honest this is really a gadget – almost totally useless :)

$wp_ozh_click['extensions'] = array ( lots of extensions )
Most common non html file extensions. These are files that have no title html tag, so their link title will be the file name ( for example)

Then, top link features :

$wp_ozh_click['top_limit'] = 5
Default number of top links to be displayed by wp_ozh_click_topclicks() (see above, Template Tags)

$wp_ozh_click['top_pattern'] = '<li><a href="%%link_url%%" title="%%link_title%%">%%link_title_trim%%</a>: %%link_clicks%%</li>'
Default pattern used to display top links (see above, Template Tags)

$wp_ozh_click['trim'] = 15
Default maximum length of link titles (0 not to trim)

Tips and Tricks

Here are listed a few tips or thoughts I've had during the development and test of the plugin.

» As a file download counter
You can use this plugin as a download counter to see how popular are your files :-P
To do so, you can either specify count="1″ in the download link html tag, or link them with an absolute file (http://site/blog/download/

» Use with Matt's Asides
If you are using Matt's asides or something similar, you'll have to modify a bit your index.php

  1. echo wptexturize($post->post_content)


  1. echo wp_ozh_click_modifyhrefs(wptexturize($post->post_content))

» Use with blogrolls
Similarily, if you want to use the feature on a blogroll link list for example, modify the php code to add wp_ozh_click_modifyhrefs().
Remember one thing : each link counter display (in title on in plain text) will cost 1 SQL query. Know what your server can handle before doing such things :)

» Invisible tracker for weak SQL servers
You can use the plugin to track clicks at no SQL cost : set $wp_ozh_click['track_all_links'], $wp_ozh_click['in_title'] and $wp_ozh_click['in_plain'] to zero. It will still modify your link html tags to add the tracker file to them, but it won't display hit counters along with links.
Now, check your link clicks from phpmyadmin directly, or using the template tag wp_ozh_click_topclicks() (1 SQL query)


1.0 :

  • Initial release

1.01 :

  • improved : only one query if same url repeated
  • fixed : no javascript in links for rss outputs (so the feed validates)

1.02 :

  • fixed potential SQL injection


It took me almost longer to write this doc than to write the plugin itself :)

Shorter URL

Want to share or tweet this post? Please use this short URL:


This entry "Click Counter Plugin For WordPress" was posted on 17/09/2004 at 4:58 pm and is tagged with , , , ,
Watch this discussion : Comments RSS 2.0.

527 Blablas

  1. Ozh says:

    Ramon Fincken » probably because when I coded this *FIVE* years ago I was much more ignorant than now :) I would probably change a bunch of things if I were to rewrite this plugin today

  2. Lucato says:

    Hey Ozh, as you're a programmer, just a suggestion for a plug-in I'm looking for. It would be cool to have one that I would jut put tags between my ad/banner code, something like [click id="Banner XYZ"]CODE[/click] and it would count and show in a table in the back the click results like:
    Banner XYZ 100
    Banner Bla 150
    Campain XT 240… and so on. ;0)

  3. ka81 says:

    Author, thanx for the plugin.
    Could you please help me – why there's not shoxing number of hits?
    images – are links.
    i installed as in you instruction. didn't change any code.

  4. ka81 says:

    I meant showing numbers in popup title

  5. Ozh says:

    ka81 » it works fine: the a tag has a title with a number of hits. But the browser is showing the title of the inner canvas element.

  6. ka81 says:

    Could you please tell me what to change that all could see the number of hits in popup title?

    in Opera 10 –
    only the title and no (xx hits)

  7. ka81 says:

    because otherway (if not shown there with title) – there's no way to see how many times it was clicked… :)

  8. Ozh says:

    ka81 » think a bit by yourself. The <a> has a title. It wraps an element (canvas) which has a title too. Only this one show. Then remove the canvas element title. You're on your own.

  9. Mabuc says:


    I updated my wordpress to WP9 version but my click counter dont work anymore… its not yet compatible in this version? please let me know…


  10. Ozh says:

    Mabuc » it's compatible with *any* WP version.

  11. Damien says:

    Bonjour Ozh,

    Tout d'abord, merci pour ce plugin ! mais aussi bonne année. Aprés avoir lu pas mal de tes commentaires, je vois que ce plugin marche chez bcp.Il semblerait donc que j ai fait quelque chose qui ne va pas, car ca ne marche pas chez moi.

    Voici les modifications que j ai faite:

    1. changer get_option ('siteurl') qui est deprecie par
    2. j ai placé go.php à la racine soit direct dans www (ovh) et pas dans le dossier de mon theme.
    3. j ai placé wp_ozh_clickcounter.php direct dans /www/wp-content/plugins
    4.enfin j ai configuré les options.

    nb:j ai bien sur créer la base comme indiqué sans probleme.

    Je comprends pas bien pourquoi rien ne s affiche.

    Merci pour ton aide et pour ce plugin que je ne trouve nulle part ailleurs.


  12. Damien says:

    re Ozh,

    Bien, j'ai tout repris depuis le début. J'ai désactivé mon theme et j'ai activé le theme par défaut de WP, le plugin fonctionne a merveille sur le theme par défaut.
    Il s'agit donc (?) d'un conflit avec mon theme, avec les plugins deja installé ou ma facon d'afficher les articles.

    A aucun moment, je n'utilise "the_content" pour afficher mes postes . Est ce que le JS de click counter a besoin de "the_content" pour s'initier ?

    Enfin voici la liste des plugins (peut etre cela pourra t'aider à m'aider ;)):
    AJAXed WordPress, Akismet, Batch Categories, Category Order, Hot Linked Image Cacher, Manageable, Posts by Author, Register Plus, Super Search, Theme My Login, WP-PageNavi, WP-PostRatings, WP Favorite Posts,WP Super Cache.

    Merci encore pour ton temps accordé à ma petite requete. En attendant je continue de chercher une solution.

  13. Damien says:

    C'est encore moi! je me dis que mes commentaires pourront peut etre servir a qq un d'autre.

    C'est donc cette fonction qui dicte le tout:

    if ($wp_ozh_click['do_posts'])
    add_filter('the_content','wp_ozh_click_modifyhrefs', 10);

    et notamment 'the_content' que je n'utilise pas. C'est pour ca que ca plante.
    J'ai rajouté pour afficher mes posts et le counter marche. Simplement, je ne peux pas utiliser .
    Ma question est donc: que puis-je utiliser pour notifier au JS que c'est ici qu'il doit compter les clics ?

    Merci d'avance pour ton aide,

    nb je ne suis pas un pro en php, c'est pour ca que modifier l'output de the_content me parait difficile a mon niveau pour faire fonctionner le counter.

  14. Dave says:

    Where does it display the DATA?

  15. ramy says:

    thanks Ozh for this amazing plugin that i expect that it can suitable for me, although i have tried to use it with my software liberary template to display the numbers of downloads for external links through special fields , but i cant, i hope that you give me the solution, thanks very much.

  16. Char Aznable says:

    Congrats for this wonderful tool! It?s great! But I have some questions:

    1. I posted my link in a picture, it is working perfectly but I want to take those "parentesis" out. What do I need to do?
    2. In this page, in hte begining, there is a counter on your page. How can I put the number of clicks to the right of my link?


  17. Ozh says:

    Char Aznable » This is a page view counter. This is not a click counter.

  18. michael says:

    I am trying to get this to work with shadowbox js plugin, to display .mov files through a flash player, and through vimeo.

    Even a regular image link / just a plain link doesn't work. I made a post with examples to help explain:
    password is: asdf

    In every case, the (no views) shows up, (in my case it says "be the first!"), but it never changes from that. Inline and title show up though

    I assume that the link is getting pulled from the originals post code, and then eventually directed to the link. But I still need the shadowbox ref="" attributes to stay intact, rather than directly going to the href="…"

    Any help is greatly appreciated

  19. Ozh says:

    michael » the javascript hijacks the link from being counted.

  20. Lucato says:

    Hey Ozh, before installing I got a few questions.
    I want just to add your plug-in to some links (like for banners only), so I don't want it to work on every sing link into my WP, just for wished ones. My doubt is. Is it possible to set your plug-in to work only in a wished link? If so, how to achieve that? Or is it possible to use some code within brackets or something like that into a post to inform that a certain link will get counted? If not yet, maybe a suggestion for a future update. ;0)

    [ClickCounter]{a href=""}link{/a}[/ClickCounter]


  21. Ozh says:

    Lucato » everything explained in the doc here

  22. Lucato says:

    I'm sorry, maybe it's due my newbie level with these codes. I didn't get to find any stuff in your document related to add the brackets into a link into a post and not how to make it work only for a specific link and not for all links as "install & forget" type. Otherwise, I hadn't post this doubt and took your time. ;0)
    Would you mind to point here or send me by e-mail how to add the brackets into the post, or the code just for wished links instead of all them. Maybe a FAQ section in your document here having these topics would be helpful for beginners like me. :0)

  23. michael says:

    Is there any easy work around for this?

  24. Ozh says:

    michael » no. Or don't use shadowbox or whatever.

  25. Syed says:

    I don't know how to show number of hits in post

    for example:

    I have link as "Sample" in a post and i am getting the result only when i hover the link.

    I would like to get result like " SaranR (450 hits) "

    Please help me

  26. Ozh says:

    Syed » You need a *pageview* counter.

  27. Jyujinkai says:

    Hi… I am having a problem…. I copy and paste the code into the SQL area of PHPmyAdmin and it errors… i am pasting this…

    CREATE TABLE `wp_linkclicks` (
     `link_url` TEXT NOT NULL ,
     `link_clicks` INT NOT NULL ,
     `link_date` DATETIME NOT NULL ,
     `link_title` TEXT NOT NULL ,
     UNIQUE (

    this is the error….

    MySQL said:
    #1064 – You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '`link_id` INT NOT NULL AUTO_INCREMENT ,
    Â `link_url` TEXT NOT NULL ,
    Â `link_c' at line 2

  28. Ozh says:

    Jyujinkai » the very same works fine with me…

  29. Jyujinkai says:

    Well it is error for me… . I looked though PHPmyAdmin and it looks like the thing is there… as in tehre is a table.. and if you go to my site you can see everything says "no click" so the plugin is working.. but when you click something and refresh nothing is changed.

  30. Jyujinkai says:

    Hmm… i dropped the table and then tried again and it worked… weird.. thanks for your time and this cool plugin

  31. busse says:


    how i can make so that when i have image, then this go does not allow to open in new window like its link.

  32. Marie says:

    I am quite a newbie from Germany I installed everything successfully, but I have a problem with the part "The archive contains the tracker file, go.php : put this file in your blog root."
    Where is my blog root? Maybe its just a problem with the translation.
    Every time I click on a link on our blog, it says: "object not found".
    Thank you a lot! Marie

  33. Ozh says:

    Marie » the blog root is well, the "root" of where you installed WP. The physical directory that matches the URL of your blog.

  34. Spruch says:

    Hello from Germany! May i quote a post a translated part of your blog with a link to you? I've tried to contact you for the topic Click Counter Plugin For WordPress « planetOzh, but i got no answer, please reply when you have a moment, thanks, Spruch

  35. Ozh says:

    Spruch » sure

  36. Monsoon says:

    A couple of important points you forgot to mention:

    – the go.php file must be put at the root of the site and not left in the plugin folder.
    – the wp_ozh_clickcounter.php needs to be put in the plugin folder and not the whole folder that is downloaded…ie just that file.
    – to see the stats you need to create a page and paste in it, that is very unclear for people who don t know php. You should really put that more clearly as I see tons of comments asking how to view the stats. One would expect to be able to see that in the admin section and not on a page that now needs to be password protected.
    – The only links counted are the ones from posts and not from links in the sidebar which would have been better for people who want to track ad clicks for example.

    Otherwise great plugin

  37. Monsoon says:

    Lets try again, you have a typo in the guidelines it should probably say you are missing a / hence why my previous post probably did not show the code…lets try again

  38. Monsoon says:

    lets try again, you need to add this to a page AND also have a way to execute php code within a post or you need to create a custom template.

    I would strongly recommend you simply had a template or explain better how people can view stats.

    1. wp_ozh_click_topclicks($limit, $trim , $pattern)
  39. Monsoon says:

    Where would you modify the code to add that all links need to open in a new window ie target="_blank".

    I am looking at the code and I am not sure where the loop needs to be modified or did I miss that option?

  40. Monsoon says:

    ok solved it myself. To open the links in another widow, in wp_ozh_clickcounter.php add

    1. $wp_ozh_click['link']['target']="_blank" ;


    1. $wp_ozh_click['link']['onmouseover']="javascript:window.status='". $wp_ozh_click['link']['href'] ."'; return false;" ;

    if you are using method 3

  41. john says:

    how can get the number of people clicked a certain link? have any shortcode or must select from the datebase?

  42. Nyces says:

    Lo. great plugin! Just wahat I need but I'm having issues – when trying to add the table. I get this error…

    1064 – You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SQL: 1.CREATE TABLE `wp_linkclicks` ( 2. `link_id` INT NOT NULL AUTO_INCREMEN' at line 1

    What am i doing wrong? Thanks.

  43. Ozh says:

    Nyces » Click on "Plain text" before copying the SQL code………..

  44. Nyces says:

    Thanks Ozh! Thats the ticket. Apologies, but now i'm recieving no database selected?

  45. Nyces says:

    Fixed it, thanks very much!!

  46. Nyces says:

    Hello again, I'm having problems after activating the plugin.

    Some links when hovering turn the cursor into a text cursor while some others links broken by adding the http: twice.

    Any ideas?

  47. kevin says:

    Hey ozh, i'm having the same problem as Nyces, the sql error. Tryed indeed with the plain text version and also by changing the ` to '. Am using wampserver. Any clue? Thanks in advance.

  48. Yuichen says:

    I'm having trouble with this plugin. I'm only testing it on one link so far and it shows that no one has clicked… but it never updates despite clicking it on tons of times. On the page or in the database. It's like it doesn't even send the information.

    What I don't understand is how it can send it when it doesn't even know what the database name and such is… I don't see a place to specify.

  49. Angie says:

    Hi, I have installed this plug in, but it just says no clicks even though it has been clicked alot. I can’t seem to figure it out, any suggestions? I did have to rename the database, but I wen thorugh all the code in the files and replaced it with the right name.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>
Gravatars: Curious about the little images next to each commenter's name ? Go to Gravatar and sign for a free account
Spam: Various spam plugins may be activated. I'll put pins in a Voodoo doll if you spam me.

Read more ?