Don't Dirty Stats with your Visits

I often spend a heap of time tweaking stuff on my blog, and these show up as hits in the Referrers list, as well as on Performancing Metrics, a system of tracking readership. Now, it’s rather simple to stop your visits counting towards your stats. First, visit your site, and ensure you are logged in. In your address bar at the top of your browser, type in javascript:document.cookie, and press return. Find the cookie entry that starts with wordpressuser_, and copy the garbage-looking string after it - this is the md5 hash of your server name - to the clipboard. Find the location of your stat-gathering code. Before it starts, enter: {if $smarty.cookie.wordpressuser_md5string != "username"} and after it ends, enter: {/if} Make sure to replace md5string with your md5 hash! • This could also be used to have any text show/not show when you visit your own blog. Like Google AdSense ads, for instance.

Performancing Stats for Blogsome

This post is a Blogsome specific post with information gleaned from HOWTO: Wordpress Visitor Count Plugin Using Metrics API. If you aren’t using Blogsome, then you’ll be better off visiting there. If you are using Performancing Metrics as your system for tracking usage patterns, you may wish to have a counter of some sort. It’s possible to do this, safely and securely with just a little bit of Smarty. First, you’ll need to get your current Performancing Authorisation Key. This will not change unless you change your password, so keep that in mind if this stops working at some stage… To get your API key, you’ll need to visit a URL like the following, but with your username and password. http://performancing.com/perfstats/api.php?action=getauth&uid;=some+user&pwd;=mypass If you put this into a Firefox address bar, it will display the XML, but the only part we need is the part inside the <auth> tags. Don’t give this to anyone, else they can see all of your Performancing stats. You can now use this key to get some stats. As a test, we’ll get the basic stats of your blog. Copy and paste the URL below, and insert it into the address bar. Then, replace KEY with your authorisation key, and schinckel with your blogsome ID:

http://performancing.com/perfstats/api.php?action=getvisitorstats&auth;=KEY&blog;_domain=schinckel.net

You’ll be presented with some XML that looks like:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
    <response>
        <request>
            <auth>KEY</auth>
            <blog_domain>schinckel.net</blog_domain>
            <action>getvisitorstats</action>
        </request>
        <ChartURL>
            http://performancing.com/perfstats/api.php?action=getchart&blog_domain=schinckel.net&dtype=visitor_stats&ctype=line&m=today&d1=2006-04-17&d2=
        </ChartURL>
        <Visits>20</Visits>
        <AverageVisitsPerDay>20.0000</AverageVisitsPerDay>
        <AverageVisitLength>517.9500</AverageVisitLength>
        <RepeatVisitors>0</RepeatVisitors>
    </response>

You can then use the ChartURL to see a nice graph, something like: Performancing Stats If this doesn’t work, then check your API key, and all of the URLs you’ve typed in so far. Now, let’s imagine we just want a counter for total blog views. The URL will need to look a bit like (I’ve broken it onto seperate lines first to help you understand it): http://performancing.com/perfstats/api.php?action=getvisitorstats &auth;=KEY&blog;_domain=blogname.blogsome.com&m;=date_range &d1;=start_date&d2;=end_date We’ll look at how to get the current date a bit later: for now, put a date at some point in the future. Mine, sans the authorisation key was: http://performancing.com/perfstats/api.php?action=getvisitorstats&auth;=KEY&blog;_domain=schinckel.net&m;=date_range&d1;=2006-01-01&d2;=2007-01-01 Which generated the following XML:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
    <response>
        <request>
            <auth>KEY</auth>
            <blog_domain>schinckel.net</blog_domain>
            <action>getvisitorstats</action>
        </request>
        <ChartURL>
            http://performancing.com/perfstats/api.php?action=getchart&blog_domain=schinckel.net&dtype=visitor_stats&ctype=line&m=date_range&d1=2006-01-01&d2=2007-01-01
        </ChartURL>
        <Visits>9204</Visits>
        <AverageVisitsPerDay>271.3529</AverageVisitsPerDay>
        <AverageVisitLength>289.5818</AverageVisitLength>
        <RepeatVisitors>242</RepeatVisitors>
    </response>

It’s possible to use the {fetch file="URL" assign="stats"} to grab this data and store it in a variable, so the whole lot isn’t displayed. You may have noticed that the Auth Key is included in the response! Now, the only bit we are really interested in is the

1
    <Visits>9204</Visits>

section, so we need some way to extract this. Smarty allows for Regular Expressions, and we want to use one that will match everything up to and including , and discard this. We’ll want to repeat that with onwards. Due to a limitation, we’ll need three regexes, since there are newlines in there that much with the simlest method.

1
    {$stats|regex_replace:"/[\r\t\n]/":""|regex_replace:"/.*<Visits>/":""|regex_replace:"/<\/Visits>.*/":""}

Thus, my final data is:

    <li>{fetch file="http://performancing.com/perfstats/api.php?action=getvisitorstats&auth=KEY&blog_domain=schinckel.net&m=date_range&d1=2006-01-01&d2=2007-01-01" assign="stats"}
        {$stats|regex_replace:"/[\r\t\n]/":""|regex_replace:"/.*<Visits>/":""|regex_replace:"/<\/Visits>.*/":""} Post views.
    </li>

Of course, that’s with a hard-coded finish date. What if we want to finish on today? Again, there’s a way to do it in $smarty: {$smarty.now|date_format:"%Y-%m-%d"} To add this to the end of the URL, use:

1
2
3
    {assign var="URL" value="http://performancing.com/perfstats/api.php?action=getvisitorstats&auth=KEY&blog_domain=schinckel.net&m=date_range&d1=2006-01-01&d2="}
    {assign var="today" value=$smarty.now|date_format:"%Y-%m-%d"}
    {fetch file=$URL|cat:$today assign="stats"}

It’s also simple to get a current day’s post hit count, using single_date instead of date_range. I’ll leave that one up to you.

Better Performancing Stats

This is a Blogsome specific version of the post that can be found at Hack Metrics for More Detail. The default script that I modified to generate Performancing Metrics stats for my Blogsome blog has some pretty serious limitations. The main one is that there is no differentiation between single posts, and the various types of archive pages that can be view: Category, Author, and Date (which includes Yearly, Monthly and Daily archive pages). To overcome this, I’ve come up with the following rationale:

  • Test to see if it’s a Page. Set the title to the Page title, and the category to “Page”.
  • Test to see if it’s the Homepage. If so, the title should be “Homepage”, as should the category. I’ve also been thinking about whether to append the title of the newset post, which would then enable some idea of how often the front page is viewed with particular posts. Then, using the category “Homepage” would enable me to still see how many homepage views there are in total. This is turning out to be harder than expected, due to some apparent malfunctioning of {rewind_posts}.
  • Test to see if it’s a category page. This should have the title and the category both set to the category name.
  • Test to see if it’s a date archive page. If it is, set the category to Archive, and the title to the date. Be a bit clever, and have different titles for Monthly, Daily and Yearly archives.
  • Test to see if it’s a search page. If so, set the category to Search, and the title to the search terms, prefixed by Search:.
  • Finally, it must be a single post page. Set the title to the post title. This is where the system breaks a little, as there doesn’t seem to be the ability to have multiple categories. This seems to be a limitation of performancing metrics.

Anyway, here’s the code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
        <script type="text/javascript">
            {if $smarty.server.SCRIPT_NAME == "/wp-inst/pages"}
                z_post_title="{single_post_title}";
                z_post_category="Page";
            {elseif $smarty.server.REQUEST_URI == "/"}
                z_post_title="Homepage"; // ({rewind_posts}{the_title}) {* Fix - gets last post title, not first *}
                z_post_category="Homepage";
            {elseif $smarty.server.REQUEST_URI|truncate:10:"":1 == "/category/"}
                z_post_title="{single_cat_title}";
                z_post_category="{single_cat_title}";
            {elseif $smarty.request.s != ""}
                z_post_title = "Search: {$smarty.request.s}";
                z_post_category = "Search";
            {elseif $smarty.request.name == ""} {* Date Archive Page *}
                {if $smarty.request.day != ""} {* Daily Archive *}
                    z_post_title="{$smarty.request.day}{single_month_title prefix=' '}";
                {elseif $smarty.request.monthnum != ""} {* Monthly Archive *}
                    z_post_title="{single_month_title prefix=' '}";
                {else} {* Must be a Yearly Archive then! *}
                    z_post_title="{$smarty.request.year}";
                {/if}
                z_post_category="Archive";
            {else} {* Single Post, or unknown *}
                z_post_title="{single_post_title}";
                {capture name=cats}{the_category seperator=","}{/capture}
                {assign var=cats value=$smarty.capture.cats|strip_tags:false|replace:', ':'","'}
                z_post_category=Array("{$cats}");
                z_post_category="{$smarty.capture.cats|strip_tags:false}"; //Remove _this_ when performancing is fixed.
            {/if}
            //z_user_name=_"{$smarty.capture.author}"_;
            //z_user_email=_"{$smarty.capture.author_email}"_;
        </script>
        <script id="stats_script" type="text/javascript" src="http://metrics.performancing.com/wp.js"></script>
    

This may change at any time, as I tweak it and so on. Visit my Template page for the most recent version (click on Main Page, and then scroll down to the bottom).

Smarty Pages

I’ve created a Popular Posts page, so I can have a limited number of popular posts in the sidebar, and the title of the box they appear in linking to a page with all of the popular posts. I’ll do the same with Recent Posts, since this will be a smaller list than Archives. Basically, it will be a list of the last 25 posts, rather than a list of all of them, or the complete text of any posts. I’ve just had another thought: for search pages, I could do some fancy stuff with testing the URL for ‘/search/’, and then generating a search from the remainder. Instead of having to wait for Rewrite Rules to be implemented. Hmm, interesting.

Human Age Smarty Modifier

The Smarty Modifier “Human Age” works well under Blogsome, I’ll ask the admins to install it. It’s used like:

1
2
3
    {capture name=pdate}{the_time d="U"}{/capture}
    {capture name=cdate}{comment_date d="U"}{/capture}
    {assign var=since value=$smarty.capture.pdate|human_age:$smarty.capture.cdate:true:2}

Then, where you want the data to go: {$since} after the fact. Note: this is not installed on the main Blogsome server yet. However, you can already use: {human_time_diff from=$smarty.capture.pdate to=$smarty.capture.cdate} after having captured the dates. It isn’t quite as nice as the other version, as it only displays minutes/hours/days, but it will do for now.

Turning off Google Ads

Michael, over at Binary Bonsai, has written about how he turns off Google Ads (or any other type of text) for readers who have commented. No Ads for Regulars at Binary Bonsai Here’s how to do the same thing at Blogsome, using Smarty Tags. Just before your Ad Block: {if $comment_author == ""} And then after, use: {/if} Then, readers who have commented on your blog won’t see your Advertisement(s). This only seems to work on a Post page. For some reason the cookie isn’t checked on other pages. I’m still looking into this.

Changing Languages

There isn’t a way to tell Blogsome you are writing in a different language, but with things like dates, that are generated using Smarty tags, there is a way to replace the English words with those of your chosen language. Where you’d normally use a tag like: {the_time d='l, j F Y'}, which would generate something like: Thursday, 23rd March 2006, you can set up your template with:

1
    {capture name=the_date}{the_time d='l, j F Y'}{/capture}

Then, assign this captured text to a new variable, after translating each word you know might appear in the text using |replace:"old":"new", which you can repeat for each word. For example, to replace all of the day names with their Spanish equivalent, and assign the result to $la_fecha, I used:

1
    {assign var=la_fecha value=$smarty.capture.the_date|replace:"Monday":"Lunes"|replace:"Tuesday":"Martes"|replace:"Wednesday":"Miércoles"|replace:"Thursday":"Jueves"|replace:"Friday":"Viernes"|replace:"Saturday":"Sábado"|replace:"Sunday":"Domingo"}

Then, wherever you want to use {the_date} in the Spanish format: {$la_fecha}. Obviously, you’ll need to repeat this for month names as well, which I will leave as an exercise to the reader.

Smarty Modifiers of Note

I’ve come across a couple of Smary Modifiers I want to have installed on Blogsome:

More available on: Smarty Plugins Wiki If there’s any more there anyone is interested in, leave a message and I’ll test them out. And then ask the admins to install them, if they work.

SubEthaEdit HTML-Smarty Mode

I’ve never been really happy with the HTML-Smarty Mode file I downloaded for SubEthaEdit. It’s okay, but it loses the syntax styling on HTML elements, and doesn’t really do that good of a job styling the Smarty parts. So, I’ve spent the last couple of hours hacking it to make it a bit better. I’d forgotten how hard it is to examine and understand regex codes, but I’m getting there. It’s too late, and I’m too tired to finish it, but it is already better than the original. • And then I go to the SEE website, and see there’s a newer version. Luckily, it’s still missing a whole heap of functionality. That’s a new project for me to work on then. My mode isn’t quite ready for human consumption, but I’ll keep working on it.

Comment/Trackback Display

I’ve made some changes on my blog template so Trackbacks are handled a little bit nicer: specifically, Trackbacks/Pingbacks now also get the “owner” class. I’ve also turned off Gravatars for Trackbacks/Pingbacks, since they don’t make that much sense. I’d like to use a favicon or something in their place, but I’m not yet sure how to do this. At this stage, I’ve left in code so that the Gravatar for the Author Email will appear for owner trackbacks/pingbacks. Here is the code I am using as of now for my Comment Loop:

    {* Variables that don't change (post/blog) *}
    {capture name=author_email}{the_author_email}{/capture}
    {capture name=author}{the_author echo=false}{/capture}
    {capture name=blog_title}{bloginfo show='title'}{/capture}
    
    
    {if $comments != ''}
      <ol id="commentlist">
      {foreach from=$comments key=key item=comment}
            {globalvar var='comment' value=$comment}
    
            {* Setup for Owner Comments, including Pingbacks & Trackbacks *}
            {capture name=comment_type}{comment_type}{/capture}
            {capture name=self_ping}{comment_type}@{bloginfo show='url'}{/capture}
            {if $comment->comment_author_email == $smarty.capture.author_email or $comment->comment_author_email == $smarty.capture.self_ping|lower|replace:"http://":"" or $comment->comment_author == $smarty.capture.blog_title}
                {assign var=owner value=owner}
                {assign var=comment_author_email value=$smarty.capture.author_email}
            {elseif $smarty.capture.comment_type == "Comment"}
                {assign var=comment_author_email value=$comment->comment_author_email}
            {else}
                {* Off-site Trackback/Pingback.  Get an image from their site? *}
            {/if}
            
            {* Gravatar Allocation.  Uses variable $comment_author_email from above. *}
            {if $comment_author_email != ""}
                {assign var=gravatar value=$comment_author_email|gravatar:"http://schinckel.net/images/NoGravatar.gif":"40":"":"0"}
                {assign var=comment_author_email value=""} {*Reset for next comment*}
            {/if}
    
            {* Set up for Alternating Comment Styles *}
            {if $alt != 'altcomment'}
                {assign var='alt' value='altcomment'}
            {else}
                {assign var='alt' value=''}
            {/if}
    
            <li class="{$owner} {comment_type} {$alt}" id="comment-{comment_ID}">
                <div class="right">{$gravatar}</div>
                {comment_author_link} said: 
    
                {if $comment->comment_approved == "0"}{*Not implemented yet.*}
                    <p><em>Your Comment is awaiting Moderation.</em></p>
                {/if}
    
                {comment_text}
    
                <!-- Admin Tools -->
                {capture name=edit_comment}{edit_comment_link link="&#9997; Edit" before='<span class="button">' after="</span>"}{/capture}
                {if $smarty.capture.edit_comment != ""}
                    <div class="right">
                        {$smarty.capture.edit_comment}
                        <span class="button"><a href="http://schinckel.net/wp-admin/post.php?action=confirmdeletecomment&comment={comment_ID}">&#10007; Delete</a></span>
                    </div>
                {/if}
        
                <a href="#comment-{comment_ID}"><span class="timesince" id="c{the_time d="U"}-{comment_date d='U'}">on {comment_date} at {comment_time}.</span></a>
        </li>
      {/foreach}</ol>
    
    {else} <!-- this is displayed if there are no comments so far -->
        <p class='indented'>{_e text="No responses yet."}</p>
    {/if}

Cosmic Girl • Jamiroquai • Travelling Without Moving ★★★