DEV Community

ahmet gedik
ahmet gedik

Posted on

Implementing hreflang Tags for a Multi-Language Video Site

If you run a site that serves content in multiple languages or regions, hreflang tags are essential for SEO. Here's how I implemented them on TopVideoHub, a video platform covering 9 Asia-Pacific regions.

What Are hreflang Tags?

hreflang tags tell search engines which version of a page to show to users in different countries or languages. Without them, Google might show your Japanese content to English searchers, or treat your regional variants as duplicate content.

The Challenge

TopVideoHub has regional variants for every page:

  • / — English (default)
  • /?region=JP — Japanese trending
  • /?region=KR — Korean trending
  • /?region=TW — Traditional Chinese (Taiwan)
  • /?region=HK — Traditional Chinese (Hong Kong)
  • /?region=VN — Vietnamese trending
  • /?region=TH — Thai trending

Each page needs hreflang tags pointing to all other variants, and the references must be bidirectional.

Implementation

I built a PHP helper that generates hreflang tags for any page:

<?php
declare(strict_types=1);

enum HreflangLocale: string {
    case EN = 'en';
    case JA = 'ja';
    case KO = 'ko';
    case ZH_TW = 'zh-TW';
    case ZH_HK = 'zh-HK';
    case VI = 'vi';
    case TH = 'th';
}

class HreflangGenerator {
    private const string BASE_URL = 'https://topvideohub.com';

    private const array REGION_LOCALE_MAP = [
        'US' => 'en',
        'GB' => 'en',
        'JP' => 'ja',
        'KR' => 'ko',
        'TW' => 'zh-TW',
        'HK' => 'zh-HK',
        'VN' => 'vi',
        'TH' => 'th',
        'SG' => 'en',
    ];

    public function generate(string $path): string {
        $tags = '';
        $baseHref = self::BASE_URL . $path;

        // x-default (English version)
        $tags .= $this->tag('x-default', $baseHref);
        $tags .= $this->tag('en', $baseHref);

        // Regional variants
        $seen = ['en' => true];
        foreach (self::REGION_LOCALE_MAP as $region => $locale) {
            if (isset($seen[$locale])) continue;
            $seen[$locale] = true;

            $separator = str_contains($path, '?') ? '&' : '?';
            $href = $baseHref . $separator . 'region=' . $region;
            $tags .= $this->tag($locale, $href);
        }

        return $tags;
    }

    private function tag(string $lang, string $href): string {
        return '<link rel="alternate" hreflang="' 
            . htmlspecialchars($lang) 
            . '" href="' 
            . htmlspecialchars($href) 
            . '" />' . "\n";
    }
}
Enter fullscreen mode Exit fullscreen mode

Usage in templates:

<head>
    <?= (new HreflangGenerator())->generate($_SERVER['REQUEST_URI']) ?>
</head>
Enter fullscreen mode Exit fullscreen mode

Sitemap Integration

Google processes hreflang more reliably from sitemaps than HTML tags. I generate a dedicated hreflang sitemap:

function generateHreflangSitemap(array $urls): string {
    $xml = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
    $xml .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"' . "\n";
    $xml .= '  xmlns:xhtml="http://www.w3.org/1999/xhtml">' . "\n";

    foreach ($urls as $url) {
        $xml .= "  <url>\n";
        $xml .= "    <loc>{$url}</loc>\n";

        foreach (HreflangGenerator::REGION_LOCALE_MAP as $region => $locale) {
            $separator = str_contains($url, '?') ? '&' : '?';
            $href = $url . $separator . 'region=' . $region;
            $xml .= '    <xhtml:link rel="alternate"'
                . ' hreflang="' . $locale . '"'
                . ' href="' . $href . '" />' . "\n";
        }

        $xml .= "  </url>\n";
    }

    $xml .= '</urlset>';
    return $xml;
}
Enter fullscreen mode Exit fullscreen mode

Common Pitfalls

1. Missing bidirectional references — If page A points to page B via hreflang, page B MUST point back to page A. Missing returns cause Google to ignore the entire set.

2. Confusing zh-TW and zh-HK — Traditional Chinese for Taiwan and Hong Kong need separate hreflang entries. They're linguistically similar but Google treats them as separate targets.

3. Forgetting x-default — Always include hreflang="x-default" pointing to your fallback version. This tells Google what to show users who don't match any specific locale.

4. Canonical conflicts — Your canonical tag and hreflang tags must be consistent. If the canonical for /?region=JP points to /, Google gets confused.

Validation

Check Google Search Console's International Targeting report regularly. It flags:

  • Missing return tags
  • Unsupported locale codes
  • Conflicting canonical/hreflang

After implementing hreflang on TopVideoHub, organic traffic from Asian search engines increased significantly. Google started showing our Japanese pages in google.co.jp, Korean pages in google.co.kr, and so on.

hreflang is one of those SEO elements that's technically simple but requires careful implementation. Get it right and you unlock traffic from markets that most English-language sites completely miss.

Top comments (0)