PHP script to generate hreflang tags I'm currently working on a website which provides content to users based on their region. As a result the website has subdirectories for the appropriate regions. For example, a pricing page would look something like this:


http://mydomain.com/ie/pricing
http://mydomain.com/gb/pricing
http://mydomain.com/fr/pricing


In order to target the appropriate search engines and signify to Google that there are different versions of the page, I've implemented hreflang tags. A good example of a site that uses these would be view-source:https://www.tripadvisor.ie/. If you view the source you will see a long list of hreflang tags to denote multiple regional versions of the page.

So, for my site, I decided to write a PHP script that would output the relevant hreflang tags on the correct page:

&lt;?php $url = $_SERVER['REQUEST_URI']; ?&gt;
&lt;?php if(strpos($url, "pricing") == true): ?&gt;
&lt;link rel="alternate" href="http://www.mydomain.com/ie/pricing/" hreflang="en-ie" /&gt;
&lt;link rel="alternate" href="http://www.mydomain.com/gb/pricing/" hreflang="en-gb" /&gt;
&lt;link rel="alternate" href="http://www.mydomain.com/fr/pricing/" hreflang="en-fr" /&gt;
&lt;link rel="alternate" href="http://www.mydomain.com/pricing/" hreflang="en" /&gt;
&lt;link rel="alternate" href="http://www.mydomain.com/pricing/" hreflang="x-default" /&gt;
&lt;?php endif; ?&gt;


However, the problem I'm facing is that if the URL contains pricing ANYWHERE it will output the above which is not correct if the URL was something like: http://www.mydomain.com/pricing-types.

To counteract this I added another if statement which checks to ensure that the word types is not present in the URL:

&lt;?php $url = $_SERVER['REQUEST_URI']; ?&gt;
&lt;?php if(strpos($url,"pricing") == true &amp;&amp; strpos($url, "types") == false): ?&gt;
&lt;link rel="alternate" href="http://www.mydomain.com/ie/pricing/" hreflang="en-ie" /&gt;
&lt;link rel="alternate" href="http://www.mydomain.com/gb/pricing/" hreflang="en-gb" /&gt;
&lt;link rel="alternate" href="http://www.mydomain.com/fr/pricing/" hreflang="en-fr" /&gt;
&lt;link rel="alternate" href="http://www.mydomain.com/pricing/" hreflang="en" /&gt;
&lt;link rel="alternate" href="http://www.mydomain.com/pricing/" hreflang="x-default" /&gt;
&lt;?php endif; ?&gt;


Would anyone have any recommendations of how I could improve my script to read the URLs and match them to the appropriate hreflang tags but being more explicit in the URLs I read?
I would think that you would want to decouple the logic you use to determine what localization to display from the logic you are using to actually render the hreflang links in HTML.

With your current approach, you are going to get into a serious mess as you try to localize additional pages in your application.

You would need to hard-code similar links to what you have shown across every page. You would also need to maintain separate hard-coded versions for each page to show the slight variations in these links based on which page the user is currently on.  For example, if user is on fr page, they should not see alternate hreflang link for fr.

You also probably need to be thinking about generating an appropriate canonical URL tag as part of this same logic.

Also, over time, you may find the need to send hreflang hints in HTTP headers instead of in HTML &lt;head&gt; element.  By decoupling your logic for determining which localizations settings are applicable for a page (more of a routing concern), from how you convey that information to the browser/spider (a display concern), you can make you logic more re-usable across your application.

If you do not already have a central class or library of classes that handle localization logic for your application, you should strongly consider this.

I think what you should be striving for is a usage pattern like the following in your display context.

HTML link example:

&lt;head&gt;
    &lt;!-- other header elements --&gt;
    &lt;?php $localization-&gt;displayAltLangLinks(); ?&gt;
&lt;/head&gt;


Header example:

&lt;?php
// PHP application bootstrapping here

// send headers
$localization-&gt;setAltLangHeaders();

// page output follows


Here I have shown a theoretical Localization class/object where you could encapsulate your logic related to: current localization being requested, localization to be served, outputting localization info to browser, etc.



I think you need a better strategy for determining what language is being requested.  Relying on $_SERVER['REQUEST_URI'] will likely make your app fragile to user input.  For example,  what if I used URI of /PRICING/ in browser?  Your current code breaks.  What if I put /es/pricing/?  Your code would be triggered even though no localization would be served, when perhaps a 404 should be returned, or even a 301 to default page.

You really need to think about handling the logic around URI rewriting/redirecting at the web server and/or application bootstrap level.  A common pattern in providing the type of URI's you are looking to use it to put in a rewrite at the web server level to redirect something like:

/fr/pricing/


to

/* for individual PHP scripts */
/pricing.php?lang=fr

/* for front-controller application with central routing */
/index.php?lang=fr


This allows you to pass the language requested as a parameter to your script.  Also, if the language segment of the URI doesn't match the languages your application supports perhaps the request falls through your rewrite rules and generates a 404 or 301 redirect depending on how you want to handle these requests.

By handling localization settings early in the response processing cycle you could also do things like look at the user's browser Accept-language request headers, any user preferences settings (cookies, session settings, use preferences stored in database, etc.), to determine when localization should be rendered and performing appropriate redirects for those users.



So to summarize:


Handle localization settings and routing for the page much earlier in response process than at display time.
Dynamically generate these link  tags(and probably canonical tag) in response to what localizations are available for the route as well and what current requested localization is.