Home > Blog > Implementing Hreflang

Implementing hreflang using a strategy pattern

hreflang-guidelinesRecently I’ve been involved in a tech audit that was mainly around hreflang implementation. The hreflang attribute specifies the language of the site depending on location. Throughout the audit, I felt that things could have been a lot easier if the developers handled the hreflang implementation slightly differently.

Currently, hreflang can be implemented in three different ways;

  1. using hreflang <link> tags (as part of the <head> section of the page)
  2. using HTTP headers
  3. using XML sitemaps (<xlink>)

You can find more information on these techniques on Google Webmasters.

As this is a fairly technical post and oriented toward actual implementation you, the reader, will need to be familiar with the term MVC and aware of its components and how they work together. For those who don’t know what MVC is, it stands for Model-View-Controller, a software design paradigm in which the code of an application is divided into three logical components: models that deals with the data/database, views which are basically what the user sees and interacts with, and controllers which coordinate data flow from between models and views, and handle the business logic (processing, computation, etc).

Here is a comparison of the three techniques from an implementation point of view.


Despite the three techniques above being equally valid and supported by Google, I found the best (easiest, more maintainable, scalable, and testable) way to implement hreflang is with <link> tags. The reasons for this are:

  1. Using <link> tags won’t clutter the business logic code (the controllers).
  2. <link> tags will be part of the page (the view), which makes it a lot easier to test and validate as compared to the other techniques.
  3. Changes to the backend database will be immediately reflected on the hreflang implementation. The changes will be immediately visible if the hreflang is implemented properly.
  4. It can be easily tested and validated using unit-testing tools such PHPUnit, etc. Also, because it is testable, hreflang issues can be easily found and addressed by developers. It can be treated just like any other issue in which a test is written to isolate the bug and prevent it from escaping, a solution is implemented to pass the test. Easy!

Now, lets look at what an hreflang implementation should do. 

In order for an hreflang to be handled properly by a search bots, it needs to do two things; first, it will ensure that each page has links to all alternative versions in different languages/locales. Secondly, it ensures that each page includes itself and states its location.

To better understand this, here’s a simple example in which a page has three different versions for three different locations “en-GB”, “en-US”, “de-ES” (for English speakers based in the UK, English speakers based in the US and German speakers based in Spain).

A valid hreflang implementation must include the following <link/> tags on each of the different versions of the same page.

<link rel=”alternate” hreflang=”en-GB” href=”URL to English content for British users” />

<link rel=”alternate” hreflang=”en-US” href=”URL to English content for US users” />

<link rel=”alternate” hreflang=”de-ES” href=”URL to German content for users in Spain” /> 

As for development, I found a strategy pattern which I believe to be best suitable to handle such cases. In a strategy pattern-based hreflang implementation, we create different strategies to handle different cases of generating the hreflang URLs. We leave it to the application to pick one of the strategies depending on the received request. The strategy is then passed to the component responsible of generating the hreflang <link> tags. In an object-oriented system, we create an HreflangGenerator object with a sole responsibility of generating hreflang <link> tags, depending on the strategy passed on by the application.

Below is a code snippet, to help understand what’s actually happening.


 * A strategy to implement hreflang, this is an interface that all strategies need to conform to, in  
 * order to be treated as valid strategies.  
interface HreflangStrategy {
     * Generates alternate <link> tags for a given input
     * @param {any} $input any input that can be used to generate the hreflang links
    public function generateUrls($input);

 * A basic implementation of Hreflang
class PageHreflangStrategy implements HreflangStrategy{
    public function generateUrls($input){
        //generate the different URLs. 
 * Another implementation for the Products section of the website. 
class ProductHreflangStrategy implements HreflangStrategy{
    public function generateUrls($input){
        //generate the different URLs. 

 * Generates hreflang <link> using a strategy set by the application
class HreflangGenerator {

    private HreflangStrategy $strategy; 

    public function __construct(HreflangStrategy $strategy = null){
        $this->strategy = $strategy;

    public function setStrategy(HreflangStrategy $strategy){
        $this->strategy = $strategy;

    public function generate($input){
        if ($this->strategy !== null){


Then in the view:

<!DOCTYPE html>
          ...... blah blah blah ....
          <?php $hreflang->generate($input); ?>
          ..... blah blah blah ...
          .... content .... 

If you would like to implement hreflang using my suggested method, here are a few simple guidelines:

  1. It is the application’s responsibility to pick the right hreflang strategy and inject it into the “HreflangGenerator” object.
  2. A default strategy should be supported in cases where no alternative versions are available for a page.
  3. In the view, $input is a variable injected by the application, it contains anything required by the strategy to generate the <link> tags.
  4. The Hreflang Generator is a singleton meaning that there should only be one instance in the application (at a time) to generate the hreflang. This simplifies the implementation as we can bootstrap the HreflangGenerator at the beginning of the application, and set its strategy later on. Often provided by a dependency injection container.
  5. In Laravel, a Facade e.g. “Hreflang” can be created to wrap the HreflangGenerator implementation, making it more consistent with Laravel’s implementation [although this has changed in Laravel 5].

Please feel free to comment or provide any feedback – we’d love to hear from you!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>