Single Page Websites and High Bounce Rates in Google Analytics

You may have noticed that it is becoming trendy to have your whole site on a single page, broke out into seperate sections. Some sites built in this manner are pretty nice. Some of these sites still have additional pages but they try to get everything important on that homepage. While I am sure there could be a debate over the effectivness of these types of designs, I want to share a solution to help you better understand what is happening on those pages.

The problem with the high bounce rate

Pages like this tend to have a high bounce rate because there is a lot of info and sometimes everything a visitor needs. By default the way a bounce happens is when no second pageview ever happens after the first. By reducing from a small site of 5 pages to a single page with 5 sections you have eliminated the possibility of a second pageview for the most part. This means people who stick around, read entire sections and then gave you a call or click offsite, may have gotten exactly what they were looking for. The analytics will not reflect that, they will show a bounce.

If a section is becoming the equivenlent of a page then maybe each of those should count as a “pageview”. This will change your analytics and inflate your numbers but as long as you are aware what it means it will provide a lot of valuable info about your single page site.

If you have used GA before you have probably copied that snippet more times than you care to remember but it is always essential. This is the line, from that code, that fires off that pageview on every page of your site, and in this case once on your single page website.

    ga('send', 'pageview');

How do we solve the inaccuracy in the bounce rate.

There are a few things that we can do to get a more accurate bounce rate. We are going to look at virtual pageviews, these are pages that we view that do not reload the page but are still pages. To add virtual pageviews you will have to add a little code to your child theme or plugin. Many of these sites use things like waypoints or scrollto to make the anchor links more pleasant. So we look for code that may look something like this (this could also be applied without any of those js animations):

$('.scroll-me a').bind('click', function (event) {
    var $anchor = $(this);
    $('html, body').stop().animate( {
        scrollTop: $($anchor.attr('href')).offset().top
    }, 1000, 'easeInOutQuad');
    event.preventDefault();
} );

This code gets ran every time a link with a class of ‘scroll-me’. So we can add some of our own code to this to fire another pageview. Right below ‘var $anchor = $(this);’ would be a good place. So we add that code from before again.

$('.scroll-me a').bind('click', function (event) {
    var $anchor = $(this);

    ga('send', 'pageview');

    $('html, body').stop().animate( {
        scrollTop: $($anchor.attr('href')).offset().top
    }, 1000, 'easeInOutQuad');
    event.preventDefault();
} );

Now it will fire an additional pageview each time a link is clicked. This still is not quite helpful though because your one page will just have a bunch of inflated pageviews. Luckily there is a third param that defaults to the current page. So if we add a param to it we can more closely measure what sections of the page are being viewed.

So now the final code looks something like

$('.scroll-me a').bind('click', function (event) {
    var $anchor = $(this);

    ga('send', 'pageview', '/' + $anchor.attr('href') );

    $('html, body').stop().animate( {
        scrollTop: $($anchor.attr('href')).offset().top
    }, 1000, 'easeInOutQuad');
    event.preventDefault();
} );

Now in your analytics you will start to see views “/#contact-us” that resemble the sections people are looking at and making your bounce rate more accurate because we are accounting for interactions.

Virtual pageviews can be fired at any point you feel they are warranted. If you have a popup that happens after a specific event you could take a similar approach there as well.

Terms being misused

As a volunteer there are some terms that we use on a frequently like “foster”, “adopt”, and “rescue”. These words are pretty straight forward; however, I am shock how many people do not know what they really mean.

Fostering dogs does not mean dogsitting your friends dog because they are an irresponsible human and signed a contract for an apartment that does not allow dogs. It means providing a dog from a shelter a temporary home until they find a permanent one (usually to avoid euthanasia). Fostering is an important part of operation for a lot of shelters. It gives dogs that need a little work/training the opportunity to be adopted. It also frees a space within the shelter for an additional dog to get an opportunity to be adopted(note: when there is not room dogs get turned away for immediate euthanasia).

Adoption: if you purchased your dog from that breeder at the 7/11 selling dogs, you did not adopt you bought/purchase a life as if it was a product. Most of the time these sellers are mass producing this “product” and that is sick(see: puppy mill backyard breeder). What is worse is I see signage from these breeders using words like “adopt”.  They will do anything to sell another “product”. Consider them far worse than a greasy car salesman.

Rescued dogs come from shelters, “rescues”, or situations that literally put the animals life in danger (which should then be turned over to a shelter for proper medical care). I have heard people say they rescued their dog from that crazy breeder lady, sure you also contributed to her business and she will take that money to breed more animals exponentially. So rescue your next animal from a shelter. They may or may not have a great rescue story but their life is on the line in most situations. If their life is not on the line, the vacancy it would create saves another who otherwise would get turned away.

I have heard people say they want a specific breed and that is why they go to a breeder. I usually respond by saying we have pure breed(not that it is better) dogs that came from a shelter. Just do some research, look on petfinder, you may even find a whole rescue dedicated to your desired breed.

Who does your site talk to? (Remote Requests)

Does your site talk to anyone?

This is a question I recently had when I was dealing with a really slow dashboard. I knew WordPress tried to load news from WordPress.org and even planet.WordPress.org. I knew there could be other situations where it loads data from somewhere else after all it shows new themes and plugins.

I was trying to figure how I could find all the URLs so I could get them white-listed for this particular site. Then I realised that I could not find it in the code itself because many of the URLs would likely be dynamic. I was trying to figure out what my next step would be. Then I had a thought, I would just build a plugin and hook into pre_http_request to find all the URLs it attempted to communicate with.

This was a really simple plugin and after running it for a few days the findings were very interested, especially with a few common plugins installed.

You can download Remote Requests here.

Thickbox in WordPress

I was recently working on a plugin and needed to load a url in the admin using thickbox. As I was building the the page that Thickbox would show up on I included add_thickbox(); and then the page content. On that page I have a link that will trigger my thickbox with the remote url. This was really easy the link ended up looking something like this

<?php
$link = "http://www.website.com?TB_iframe=true&width=1200&height=800";
?>
<a href="<?php echo $link; ?>" class="thickbox">Details</a>

So you can see you have to include the class of thickbox on the anchor tag and then add the required paramaters to the url. Notice that you must set a width and height, this was somewhat problematic for me because I need it to be as large as possible and you never know what resolution the user may be using.

I needed to find a work around to solve my problem. This is what I came up with.

 

<script type=”text/javascript”>
jQuery( ‘.thickbox’ ).each( function( index, value ) {
var w = window.innerWidth * .85;
var h = window.innerHeight * .85;
var href = jQuery( this ).attr(‘href’);
var find = ‘width=1200&height=800’;
var replace = ‘width=’+w+’&height=’+h;
href = href.replace( find, replace )
jQuery( this ).attr( ‘href’, href );
} );
</script>

 

During my search I came across trac ticket #17249. It seems to have a need for a non-fixed size.

WordPress Transients and APIs

WordPress transients and APIsRecently I have been playing with wp_remote_get to retreive some data from an API. I relized that this was calling the api on every page load. While your site may or may not have a lot of traffic, this is unecessary. Using the built in transient API you can store the data for a given amount of time. Depending on how fresh your data needs to be, will determine how long you should set the expiration. For my use a DAY_IN_SECONDS seemed reasonable. Now one site will only make 1 request per day instead of every page load.

Here is the original line of code


$results = wp_remote_get( $url );

Here is the code after adding the transient


if( false === ( $results = get_transient( 'mh-api-call' ) ) ) {
$results = wp_remote_get( $url );
set_transient( 'mh-api-call', $results, DAY_IN_SECONDS );
}

Since this code will be distributed, I think it will reduce the requests significantly. I will follow up once I have more numbers.

Hide Old Shortcodes – WordPress Plugin

Hide Old Shortcodes WordPress PluginRecently I was asked to build a new WordPress theme for a project. As I was looking through some of the old content I kept noticing different shortcodes that must have existed in the previous theme or plugins. I wanted to clean these up by removing them but this site had 1000s of posts and it would be time consuming to find all of the post with shortcodes and then remove them.

I looked for an existing plugin and found a few, but you needed to enter the shortcodes into a field for them to be ignored. In this case I did not know what the shortcode was without finding it first.

I knew there had to be a better way to go about this. So I started by looking into the core code in WP for shortcodes to see if there was a filter to use to catch shortcodes that no longer existed. However when I first found the regex for shorcodes I noticed it only looked for shortcodes that were registered in WP. Kinda a dead end on that. I then decided it must be possible to use the same regex(it is a complicated one) with a few changes and find anything that looked like a shortcode. This continued to a plugin that logged all of the non-existing shortcodes.

As I monitored the log I started to notice a few false positives, that is things that were being hidden and should not have been. I knew at this point my plugin would need to account for this and be able to handle it. I then added some actions you can take on the found shortcode. You can Allow the shortcode to show, remove it from the post or edit the post in case it was a typo or something. I found this plugin pretty helpful for myself during this project so I put it up on github.

Let me know if you questions or comments about the plugin. I will be submitting it to the wp.org repo soon. I want to test it a bit more before I put it up there.

You can download Hide Old Shortcodes here.