Hreflang attributes communicate to search engines which language or regional version of a webpage is relevant to the user. This helps to avoid duplicate content issues and improve user experience by directing visitors to the most appropriate page version. Here we’ll walk through the dynamic implementation of hreflang attributes in WordPress, including a practical PHP […]
Hreflang attributes communicate to search engines which language or regional version of a webpage is relevant to the user. This helps to avoid duplicate content issues and improve user experience by directing visitors to the most appropriate page version.
Here we’ll walk through the dynamic implementation of hreflang attributes in WordPress, including a practical PHP code example to simplify your global SEO efforts.
en for English or fr-fr for French (France).<head> section of your HTML or included in the HTTP headers or website sitemap.Insert the dynamic hreflang generation script into the <head> section of your WordPress `header.php` file.
Here is a PHP example for dynamically implementing hreflang attributes.
<?php
global $wp;
$current_url = get_permalink();
// Improved function to check if the page should be noindexed
function is_noindex() {
// Check if WordPress discourages search engines
if (!get_option('blog_public')) {
return true;
}
// Check if any SEO plugins or theme functions have added a noindex meta tag
ob_start();
do_action('wp_head'); // Capture only wp_head() actions, avoiding duplication
$head_content = ob_get_clean();
return strpos($head_content, '<meta name="robots" content="noindex"') !== false;
}
?>
<link rel="canonical" href="<?php echo esc_url($current_url); ?>">
<?php if (!is_noindex()) : ?>
<link rel="alternate" hreflang="en-au" href="<?php echo esc_url($current_url); ?>">
<link rel="alternate" hreflang="x-default" href="<?php echo esc_url($current_url); ?>">
<?php endif; ?>
<?php wp_head(); ?>
</head> </html>" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button">
<!DOCTYPE html>
<html lang="<?php echo esc_attr(get_bloginfo('language')); ?>">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<?php
global $wp;
$current_url = get_permalink();
// Improved function to check if the page should be noindexed
function is_noindex() {
// Check if WordPress discourages search engines
if (!get_option('blog_public')) {
return true;
}
// Check if any SEO plugins or theme functions have added a noindex meta tag
ob_start();
do_action('wp_head'); // Capture only wp_head() actions, avoiding duplication
$head_content = ob_get_clean();
return strpos($head_content, '<meta name="robots" content="noindex"') !== false;
}
?>
<link rel="canonical" href="<?php echo esc_url($current_url); ?>">
<?php if (!is_noindex()) : ?>
<link rel="alternate" hreflang="en-au" href="<?php echo esc_url($current_url); ?>">
<link rel="alternate" hreflang="x-default" href="<?php echo esc_url($current_url); ?>">
<?php endif; ?>
<?php wp_head(); ?>
</head>
</html><html lang="<?php echo esc_attr(get_bloginfo('language')); ?>">
lang attribute using get_bloginfo('language').<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
global $wp;
$current_url = get_permalink();
get_permalink() to get the current page URL dynamically.$wp->request.is_noindex() Functionfunction is_noindex() {
// Check if WordPress discourages search engines
if (!get_option('blog_public')) {
return true;
}
// Check if any SEO plugins or theme functions have added a noindex meta tag
ob_start();
do_action('wp_head'); // Capture only wp_head() actions, avoiding duplication
$head_content = ob_get_clean();
return strpos($head_content, '<meta name="robots" content="noindex"') !== false;
}
noindex meta tag.get_option('blog_public').true (noindex enabled).wp_head() Without Duplicating It:
ob_start() to temporarily capture the content generated by wp_head().do_action('wp_head'), which only triggers wp_head() actions (without executing wp_head() twice).ob_get_clean() to retrieve the output and search for the noindex meta tag.true if a <meta name="robots" content="noindex"> tag is found, meaning the page should not be indexed.<link rel="canonical" href="<?php echo esc_url($current_url); ?>">
<?php if (!is_noindex()) : ?>
<link rel="alternate" hreflang="en-au" href="<?php echo esc_url($current_url); ?>">
<link rel="alternate" hreflang="x-default" href="<?php echo esc_url($current_url); ?>">
<?php endif; ?>
hreflang="en-au" to indicate that this page is the Australian English version.hreflang="x-default" to provide a fallback version when no other language matches.noindex pages with alternate versions.wp_head() Execution<?php wp_head(); ?>
<head> section.wp_head() was unintentionally called twice).For an in depth breakdown of this script visit our GitHub repository you will find the project Wiki and a second script built to handle bi lingual websites.
Hreflang attributes are HTML tags that specify the intended language and regional targeting of a webpage. These tags provide a roadmap for search engines to navigate between language variations of your site.
HTML Tags: Insert <link rel="alternate" hreflang="x" href="URL" /> tags in the <head> section of your webpage. This method is ideal for sites where you can directly edit the HTML and want hreflang attributes to load with the page content.
HTTP Headers: Use HTTP headers to add hreflang attributes for non-HTML files (like PDFs). The server sends hreflang details in the HTTP response header, making this a suitable option for downloadable resources that lack an HTML structure.
Sitemap: Include hreflang annotations in your XML sitemap. This is a scalable and centralised approach for websites with multiple pages and languages. It allows you to manage all hreflang attributes in one location without modifying individual pages.
Use the technicalseo.com Hreflang Testing Tool to confirm proper configuration of your hreflang attributes.
For additional WordPress functionality scripts, visit our GitHub Repository.
x-default tag as a fallback for unmatched regions or languages.For more helpful scripts and WordPress resources, check out our WordPress Functionality GitHub Repository. If you have any questions or need further assistance, feel free to leave a comment below!
John O'Connor is the founder and principal engineer of Web Lifter, a Brisbane software studio building custom software, AI systems, and structured data for Australian SMBs. He has spent over eight years shipping production AI and backend systems, and writes about what actually holds up once the demos are over. Everything published here is drawn from systems running in production for real clients.