In: , , , ,
On: 2004 / 09 / 17
Shorter URL for this post: http://ozh.in/2a

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` (
  2.  `link_id` INT NOT NULL AUTO_INCREMENT ,
  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.

Install

Download the plugin :
ozh-click-counter.zip
Extract and upload to your blog, preserving directory structure if any.
Note: download counter here and stats on wordpress.org 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="http://www.link.com/page.php">link</a>

becomes

  1. <a href="yourblog/go.php?http://www.link.com/page.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, "http://www.this-is-a-link.com/page.php" 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 (http://site.com/somefile.zip for example), it will be replaced by the document name (somefile.zip)

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="http://site.com/" 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="http://site.com/" title="69 hits">link</a>
  • count = "inline" : number of hits added in plain text, after the link : <a href="http://site.com/" >link</a> (69 hits)
  • count="title inline" : both : <a href="http://site.com/" 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="http://site.com"> will become :

  • Method 1:
    <a href="http://site.com" onclick="window.location='/go.php?http://site.com'; 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?http://site.com">
    Cool : works with "open in new window" and doesn't require Javascript enabled
    Less cool : shows ugly link "/blog/go.php?http://site.com" in status bar
  • Method 3:
    like method 2 but also modifies status bar to hide the ugly and sometimes annoying "yoursite.com/blog/go.php?" part with onmouseover="javascript:window.status='http://site.com'; 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 (somefile.zip 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/file.zip)

» 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
Replace

  1. echo wptexturize($post->post_content)

with

  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)

History

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

Wow

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: http://ozh.in/2a

Metastuff

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. R@lf says:

    The plugin worked fine till I upgraded to 1.5.. strange.

  2. Andy Skelton says:

    Ditto, R@lf. But I wasn't too busy at work today so I worked out the issue. The trouble is with the go.php. The "Status: 303 See Other" header must be sent along with the "Location: url=$url" header. If your server is running Apache, you can take out the if(…is_IIS…) stuff and just have it send the Status and Location headers and it should work fine.
    Cheers!
    Skeltoac

  3. MJ Barczyk says:

    Great script, just what i needed. I got a problem tho and i dont know whats wrong. The script is not redirecting to the linked page!

    Example:

    A window pop-ups with this adress and shows a 404 error for my homepage (nor redirecting):
    http://www.barczyk.se/dzoker-pl/go.php?http://exet.nu/html/bildarkiv/bilder/pussycat.jpg

    I did everything by the manual. Using method 3.

  4. MJ Barczyk says:

    LOL… i'm such an idiot. i forgot to create the go.php page… no wonder that the pluging didnt work hehe.

  5. Ozh says:

    great to hear it works :)

  6. […] r Download Abgelegt unter: Neues Seit ich in meinem Blog den ClickCounter von frenchfragfactory installiert habe, wurde das Theme scho […]

  7. Dan says:

    When trying to redirect, nothing but a blank page comes up… It seems to be caused by wp-blog-header.php inclusion…. If I move the redirect before it, it works.

  8. Ozh says:

    It may redirect, but it won't increment the counter. What version of WP are you using ?

  9. […] ine to your side bar {getrecentcomments quantity='5′, length='7′} Click counter plugins new page management locations dash […]

  10. […] nsit…Referrer Spammers, again. Over at […]

  11. dekay says:

    Funny excerpt from my trackback. Just wanted to let you know about some weird bug in your plugin. A website entered in a comment without a proper html-tag will not work anymore. Just like this http://www.dekay.org.

    I suppose one with a tag will work, though.

  12. Ozh says:

    It's not a bug, it's a feature :) As stated in this page, the plugin works with correct xhtml syntax.

  13. Stephen says:

    I am getting a problem like Dan, trying to use this plugin on a friend's blog. It's freshly upgraded to 1.5. It will send me to a blank page on Firefox if I leave go.php as the original, and in Internet Explorer, a "Page not found" will be returned to me.

  14. Sleepwalker says:

    Great plugin. I use it at my site, "Shifts, Twists, and Turns"

    One request though: Can you make it also track links generated by links in categories instead of only links in posts? It'd be great to know how many times people click on items in my blogroll, links list, etc. Problem here is that I cannot tweak your code or my WordPress blog code since I used Blogsome, who only allows the use of Smarty tags. So if you add that feature to your plugin, which is used at Blogsome, then it'd work for everybody there. Provided of course that Blogsome updates to a proposed new version with that feature.

  15. Ozh says:

    Sleepwalker, I'll give it a try when I have some free time

  16. Rainer Bendig says:

    HI,

    this plugin doesn't work on my new , clean wordpress 1.5 install. The page is just blank. I deleted all the checks for IIS and the var itself, but it left blank :-(

  17. Rainer Bendig says:

    oh i forget to tell… an echo $url is echoing the right target :-(

  18. Ozh says:

    to people who cannot make it work : tell me more about your config. In particular : do you have wordpress installed in the same directory than your other php files ?

  19. Rainer Bendig says:

    /var/www/html/

  20. R@lf says:

    What is the problem when I get these errors?
    PHP Warning: feof(): supplied argument is not a valid stream resource
    PHP Warning: fgets(): supplied argument is not a valid stream resource

  21. Ozh says:

    This error means the script tries to open a file, to determine its title, which is invalid ?
    Anyway, all the "fetch remote page title" stuff is not such a good idea, for many reasons. You should not use it, and I should release a new version of this script without the unnecessary options and features :)

  22. […] вная

    « MetaWishlist.com

    Click Counters

    Click Counter Plugin For WordPress и Count My Clicks &# […]

  23. Heike says:

    I am not quite sure, whether I could use this reply as a support request…

    First thank you for the fabulous doc! I am a total newbie, but I could download, install, create the table and activate the plug in. It even counts my hits!

    The only problem is, that now every link creates a "page not found". I am using WordPress 1.5 and the WP-default(German) theme. My weblog is in root/wordpress. So I installed it first in root/phpMyAdmin-2.6.1-pl3 and then I tried root/wordpress/phpMyAdmin-2.6.1-pl3. Neither works.

    What did I do wrong?

  24. […] – Use shortcuts instead of often enter texts (in posts). […]

  25. […] ugins zu verwenden. Derzeit nutze ich: Jvisitors Click Counter SecureImage werden wo […]

  26. […]

    Click Counter Plugin For WordPress

    Click Counter Plugin For WordPress &#8 […]

  27. Steve Weintraub says:

    Hi there. I installed this plugin to track downloads of files, but the url for the files doesn't redirect to go.php. I did make the path absolute. I think the problem might be the way I'm using wp tags? My code is automatically turning the post name into the download pathname. Here's the code:

    post_name;?>.zip">Download ""

    All my other urls work fine with the plugin, including internal ones that are absolute. Only these aren't working.

    Ideas?

  28. Steve Weintraub says:

    Hrm my code got messed up. Here it is again, with (..)


    (a href="http://www.website.com/downloads/(?php echo $post->post_name;?).zip")Download "(?php the_title(); ? )")/a)

  29. Ozh says:

    I'm not sure I understood… Where are you using these PHP tags ? Within a post ? If so, WP doesn't interpret your php code unless you have a plugin like RunPHP or some name like this. What is the HTML result of your weird tag ? (View Source of your result page)

  30. Steve Weintraub says:

    It's in the loop in my template.

    the output is clean html:
    Download "filename"

  31. Ozh says:

    My plugin tracks links in posts, not somewhere in your template

  32. GeekThug says:

    I can't get it to work. It keeps track of all the clicks but it does not navigates correctly. It navigates to a blank page that has http://geekthug.com/go.php?http://xbox.com in its address box. What's up with that?

    Could it be the theme I'm using? Its CleanBreeze (http://chris.coggburn.us/cleanbreeze/).

    I've tried the
    "echo wp_ozh_click_modifyhrefs(wptexturize($post->post_content))"
    tweak, but that didn't help.

  33. […] l/guided and copy two files. You can find the plugin here. Very usefull.
    […]

  34. […] vos. Se diferencia de los demás plugins con igual objetivo en su enfoque minimalista. […]

  35. netpad says:

    i am try to get i work but i have this problem.
    Warning: Cannot modify header information – headers already sent by (output started at /home/satplaza/public_html/wordpres/wp-content/plugins/wp_ozh_clickconter.php:537) in /home/satplaza/public_html/wordpres/go.php on line 7

    Warning: Cannot modify header information – headers already sent by (output started at /home/satplaza/public_html/wordpres/wp-content/plugins/wp_ozh_clickconter.php:537) in /home/satplaza/public_html/wordpres/go.php on line 7

    Warning: Cannot modify header information – headers already sent by (output started at /home/satplaza/public_html/wordpres/wp-content/plugins/wp_ozh_clickconter.php:537) in /home/satplaza/public_html/wordpres/go.php on line 7

    Warning: Cannot modify header information – headers already sent by (output started at /home/satplaza/public_html/wordpres/wp-content/plugins/wp_ozh_clickconter.php:537) in /home/satplaza/public_html/wordpres/go.php on line 24
    netpad

  36. Ozh says:

    edit the files properly, i.e. make sure there are no beginning or trailing space.

  37. Epper says:

    Hi, this is a great plugin.

    I wanted to add the counter to the output of get_links function in WordPress so I wrote wp_ozh_click_modifyhrefs(get_links());

    But it doesn't modify anything. Why? :|

  38. Epper says:

    I solved the previous problem but I think to have found a bug.

    When you show the Most Clicked links using your template and the link have some queries (such as: http://www.hello.com/index.php?p1=one&p2=two&p3=three) the chatacter & is not replaced by &

    In this way the code can't be valid xhtml

  39. Epper says:

    In the previous comment i wanted to write:
    […]
    When you show the Most Clicked links using your template and the link have some queries (such as: http://www.hello.com/index.php?p1=one&p2=two&p3=three) the chatacter & is not replaced by & &amp;
    […]

  40. Ozh says:

    Ok, thanks for the notice, indeed it breaks validation. I'll tune this if/when I update the plugin :)

  41. lahr says:

    just a cool plug – THANKS ;))

  42. […] arate them out in a posting page. […]

  43. Wilfred says:

    Epper asked why wp_ozh_click_ modifyhrefs( get_links()); did not work. Apparantly he found the answe himself. Unfortunately I cannot figure out why this is not working. Do you have any suggestions?

    Also, I'm using wp_ozh_click_topclicks with %%link_url%% in the title-attribute. This already prefixes the actual URL with the go.php. Do you have any way to not prefix the URL in this case. This makes the title so long that I cannot see the real URL.

  44. Wilfred says:

    If I'm not really clear in describing the problem with the title-attribute, please have a look at the Popular Links in the sidebar of http://blog.niftypaint.nl/blog/ Hover over any of the URLs to see the title. I would like to see the URL without the http://blog.niftypaint.nl/blog/go.php

  45. Ozh says:

    Using the plugin's defaults, here is what I get, which looks like what you're trying to get. So I guess you changed something somewhere.

  46. Wilfred says:

    The format I use is <li>%%link_clicks%% – <a href="%%link_url%%" title="%%link_url%%"gt;%%link_title_trim%%</agt;</ligt;

    In the title attribute I use the %%link_url%%. This becomes something like http://blog.niftypaint.nl/blog/go.php?REALURL. This string is so long that my browser truncates it and appends …

    What I would like to show in the Title attribute is the original URL without the prepended http://blog.niftypaint.nl/blog/go.php. Is there a substitution-variable available to accomplish this?

    In your example, it looks like you're showing the title of the target document and not the URL. You can see what I mean in the sidebar of http://blog.niftypaint.nl.

    BTW. Thanks for the otherwise great plugin!

    Also do you have a clue why wp_ozh_click_ modifyhrefs(get_links()); does not seem to work in the sidebar?

  47. Wilfred says:

    I've added
    $html = preg_replace ( "/%%link_origurl%%/i", "$result->link_url", $html);
    to wp_ozh_click_topclicks

    This enables the string "%%link_origurl%%". I use that in the title attribute in my wp_ozh_click_topclicks sidebar format-string

  48. Wilfred says:

    Another hack I made is in the JavaScript that's created when using method 3. It ended with a "return false;". At least in my installation of MS IE6 SP2 on WinXP this caused the message in the statusbar to NOT be set. I've changed it to "return true;" and now it does set the message.

    Was there a specific reason why you used return false?

  49. Ozh says:

    ok, first, please try to make up a bit your mind and post like one message with all of your questions. Thanks :)

    Then, as I said, the result I get is using the plugin's defaults. So just look at the plugin's default here, and you'll notice that it's not using %%link_url%% in the title, but, guess what, %%link_title%%. It shows the URL, not title of the document, if you set to false the very useless $wp_ozh_click['get_title'] var.

    As for wp_ozh_click_ modifyhrefs(get_links()), it can't work : get_links prints things, there's no way to make it only return things, so it's not passing any value to my function. By the end of this century I'll update this plugin and add a function to include links and blogrolls :)

    And finally, concerning the javascript part, I don't remember, probably because I mostly suck at javascript, and because it doesn't behave the same way on Firefox, so I just didn't really bother with this.

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 ?