Day 13 - Adding Custom Headers

Adding Headers to help with Search Engine Results

Headers and Google

A while ago we noticed our site was slipping from Google after we switched over to Catalyst. Strange. Nothing had changed much content-wise, but we realised that our headers had.

We also have a few other domains pointing to our main site, so after changing them to 301 Redirects (and not 302), and with the help of our new headers, we were soon back to where we were before (if not better).

Let's tell you how!

$c->response->headers->header()

$c->response->headers->header() is the main method we'll be adding to, so what do we need?

Well, we looked around at some of the bigger sites like http://www.bbc.co.uk, http://www.redhat.com etc. and did:

    HEAD -S http://www.bbc.co.uk

The main thing we noticed was that we had a missing Last-Modified header.

Creating a Last-Modified Header

As our site is a mixture of static and random content, we decided to use the last time our *.tt templates we modified, as this is the static text.

Adding the Last-Modified header is quite easy using the power of Template Toolkit.

In every content template, simply USE the date plugin e.g.:

    [% PROCESS base/header.tt %]
    [% USE date %] 

    <h1>My Content Page</h1> 

    [% PROCESS base/footer.tt %]    

Then in your footer.tt:

    [% SET lastmod = date.format(template.modtime,
                                 format => '%a, %d %b %Y %H:%M:%S GMT',
                                 locale => en_GB, ) %] 	

    [% c.stash.modtime = lastmod %]                 

    <p class="updated">Page Last Updated: [% lastmod %]</p>                 
    <!-- footer END --> 

You can see we are using the date plugin in the content template, which pulls in the modtime from that template, and not the footer.tt or header.tt. Then, from within the template, we put this value into our stash to use in our Root.pm Controller.

Adding the Header

Now we need to get this into your Root.pm:

    =head2 end

    =cut

    sub end : ActionClass('RenderView') {
        my ( $self, $c ) = @_;

        # Forward to View unless response body is already defined
        $c->forward( $c->view('TT') )
          unless $c->response->body
          || $c->response->status =~ /^3\d\d$/;

        # Set our headers

        # Last-Modified
        my $modtime = $c->stash->{modtime}; # set in template

        $c->response->headers->header(
            'X-Powered-By'  => "Catalyst/" . Catalyst->VERSION,
            'Last-Modified' => $modtime,
        );
    }

Simple!

We hope that's given you some things to think about. Have fun! ;-)

Warning

Please make sure you understand what headers do before implementing this technique, and what your site needs. If in doubt, use a search engine or speak to the Catalyst community. Thanks!

AUTHOR

Gavin Henry ghenry@suretecsystems.com