PHPackages                             mage2kishan/module-hreflang - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Localization &amp; i18n](/categories/localization)
4. /
5. mage2kishan/module-hreflang

ActiveMagento2-module[Localization &amp; i18n](/categories/localization)

mage2kishan/module-hreflang
===========================

Panth Hreflang — multi-language/multi-region hreflang link tags for Magento 2 with x-default, cross-store CMS/product/category mapping, and admin CRUD.

1.0.13(3w ago)030↓50%proprietaryPHPPHP ~8.1.0||~8.2.0||~8.3.0||~8.4.0

Since Apr 22Pushed yesterdayCompare

[ Source](https://github.com/mage2sk/module-hreflang)[ Packagist](https://packagist.org/packages/mage2kishan/module-hreflang)[ Docs](https://kishansavaliya.com)[ RSS](/packages/mage2kishan-module-hreflang/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (8)Versions (15)Used By (0)

Panth Hreflang — Multi-Language / Multi-Region Hreflang Link Tags for Magento 2 (Hyva + Luma)
=============================================================================================

[](#panth-hreflang--multi-language--multi-region-hreflang-link-tags-for-magento-2-hyva--luma)

[![Magento 2.4.4 - 2.4.8](https://camo.githubusercontent.com/079c832211eed4f9451ebe264e3865f825b0f9f31b041cbf03676c6e254535d4/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4d6167656e746f2d322e342e342532302d2d253230322e342e382d6f72616e67653f6c6f676f3d6d6167656e746f266c6f676f436f6c6f723d7768697465)](https://magento.com)[![PHP 8.1 - 8.4](https://camo.githubusercontent.com/56b3cce18841623e2cbed2ebf09b06be1be8807e99e6e054a89d304ab4790b8e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e312532302d2d253230382e342d626c75653f6c6f676f3d706870266c6f676f436f6c6f723d7768697465)](https://php.net)[![Hyva Compatible](https://camo.githubusercontent.com/14365166e02048aff917dd0a015feecdae28499fbde05fa17abd4f7821ea1139/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f487976612d436f6d70617469626c652d3134623861363f6c6f676f3d616c70696e65646f746a73266c6f676f436f6c6f723d7768697465)](https://hyva.io)![Luma Compatible](https://camo.githubusercontent.com/3c1945ee121ef64870a6f3583c91ffdfb4d8ffc35809e7ce34ca549a357e1ded/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c756d612d436f6d70617469626c652d6f72616e6765)[![Packagist](https://camo.githubusercontent.com/3361680d28b9152edffd11c2e976ac61682355476a4deac7fd7d55f547d142ae/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5061636b61676973742d6d616765326b697368616e2532466d6f64756c652d2d687265666c616e672d6f72616e67653f6c6f676f3d7061636b6167697374266c6f676f436f6c6f723d7768697465)](https://packagist.org/packages/mage2kishan/module-hreflang)[![Upwork Top Rated Plus](https://camo.githubusercontent.com/6f72584179420c41ed90432fd2579a4ed36199d4229e8181d20f353c1c4ee4eb/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5570776f726b2d546f702532305261746564253230506c75732d3134613830303f6c6f676f3d7570776f726b266c6f676f436f6c6f723d7768697465)](https://www.upwork.com/freelancers/~016dd1767321100e21)[![Website](https://camo.githubusercontent.com/f1ae86d28e2b505aee60f240d3e5508e390b0a8dc7a9b7ecf1b450fad862053f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f576562736974652d6b697368616e736176616c6979612e636f6d2d304439343838)](https://kishansavaliya.com)[![Get a Quote](https://camo.githubusercontent.com/0b6c02cc1ad00f11bf1b0164a9998734bd716473db36cc2a5c1517e3d3578d1b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4765742532306125323051756f74652d46726565253230457374696d6174652d444332363236)](https://kishansavaliya.com/get-quote)

 [![Panth Hreflang — Google is picking the wrong version of your product pages. Without the module, a UK shopper searching for a leather backpack gets the US SERP card with USD pricing. With Panth Hreflang, they see the UK SERP card with £ pricing. Google serves the right localized version to the right shopper.](docs/images/hero-banner.png)](docs/images/hero-banner.png)

> **Every multi-store Magento catalog gets hreflang wrong the first time.** The core `Magento_Store` module does not emit `` tags on any page, so Google treats two localized versions of `/women/tops` as duplicate content and picks one to index — arbitrarily. **Panth Hreflang** adds the missing layer: admin-managed groups that pair any `product`, `category` or `cms_page` across store views, automatic `x-default` emission, locale fallback to the store's Magento locale (`general/locale/code` converted to BCP 47), URL auto-resolution from `url_rewrite` on save, a three-way CMS matching strategy for the common case where you don't need to create a group per page, and a self-diagnostic on the config page that flags common misconfigurations before you ship. Theme-agnostic — the rendering path is a head block + plain phtml, so the exact same `` tags ship on Hyva and Luma with zero template overrides.

Single-locale stores still benefit: the ViewModel emits a self-referencing `x-default` so the page always declares its intent to search engines. Store-assignment edge cases (a product that exists on store 1 and 3 but not 2) are handled by the scope setting — `website` restricts hreflang to stores in the same website, `global` includes every storefront store. Deactivating a group from the grid immediately stops its tags from rendering, so you can stage content without forcing a cache flush.

---

Demo
----

[](#demo)

End-to-end admin flow — open Configuration, confirm the diagnostic is all green, navigate to the Hreflang Mapping grid, add a new group, pick the entity type, add two members with the store / ID / locale / URL / default fields, and save. Click to play.

[![Panth Hreflang demo](docs/images/demo.gif)](docs/images/demo.gif)

---

Need Custom Magento 2 Development?
----------------------------------

[](#need-custom-magento-2-development)

 [ ![Get a Free Quote](https://camo.githubusercontent.com/eac8c45d21cff8b139ddc392325f3bd6c8266a6f3d7b23f15131c958f3d3c8d0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f476574253230612532304672656525323051756f74652532302545322538362539322d5265706c7925323077697468696e2532303234253230686f7572732d4443323632363f7374796c653d666f722d7468652d6261646765) ](https://kishansavaliya.com/get-quote)

### Kishan Savaliya

[](#kishan-savaliya)

**Top Rated Plus on Upwork**

[![Hire on Upwork](https://camo.githubusercontent.com/b69353d3c6e192f4d03cc36bb8883612004e32f54dd2dbcc1e700dd791acd875/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f486972652532306f6e2532305570776f726b2d546f702532305261746564253230506c75732d3134613830303f7374796c653d666f722d7468652d6261646765266c6f676f3d7570776f726b266c6f676f436f6c6f723d7768697465)](https://www.upwork.com/freelancers/~016dd1767321100e21)

### Panth Infotech Agency

[](#panth-infotech-agency)

[![Visit Agency](https://camo.githubusercontent.com/bbf04bdd2aff502082508568ec42ace3a7475c98756f596e2013056c89726ed6/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f56697369742532304167656e63792d50616e7468253230496e666f746563682d3134613830303f7374796c653d666f722d7468652d6261646765266c6f676f3d7570776f726b266c6f676f436f6c6f723d7768697465)](https://www.upwork.com/agencies/1881421506131960778/)

---

Table of Contents
-----------------

[](#table-of-contents)

- [Preview](#preview)
- [Features](#features)
- [How It Works](#how-it-works)
- [Compatibility](#compatibility)
- [Installation](#installation)
- [Verify](#verify)
- [Configuration](#configuration)
- [Managing Hreflang Groups](#managing-hreflang-groups)
- [Storefront Rendering](#storefront-rendering)
- [Testing Your Hreflang Tags](#testing-your-hreflang-tags)
- [Troubleshooting](#troubleshooting)
- [Support](#support)

---

Preview
-------

[](#preview)

### Admin

[](#admin)

**System configuration** — **Stores → Configuration → Panth Extensions → Hreflang**. Four store-scoped toggles (Enabled, Emit x-default, Hreflang Scope, CMS Page Relation Method) plus an automated Configuration Diagnostic panel that checks every group has an x-default member, every group has at least two members, every participating store has a locale configured, no two members in the same group share a locale, and every member store has hreflang enabled.

[![Admin configuration](docs/images/admin-config.png)](docs/images/admin-config.png)

**Hreflang Mapping grid** — one row per group with columns for ID, Group Code, Entity Type (product / category / cms\_page), Members (aggregate count of linked store rows), Active flag, Created timestamp and per-row Edit / Delete actions. Mass actions let you enable, disable or delete groups in bulk.

[![Admin grid](docs/images/admin-grid.png)](docs/images/admin-grid.png)

**Edit Hreflang Group form** — General fieldset with Entity Type, Group Code, Notes and Active toggle, plus a Members fieldset with a dynamicRows editor that adds one row per store view. Each row carries Store View, Entity ID, Locale (blank falls back to the store's Magento locale), URL (blank auto-resolves from `url_rewrite` on save) and an Is Default toggle that drives the `x-default` emission. The toolbar above the grid has Browse Products / Browse Categories / Browse CMS Pages buttons — each one dims when the group's Entity Type doesn't match, and opens a searchable modal so admins can look up the right ID by name.

[![Edit group form](docs/images/admin-edit.png)](docs/images/admin-edit.png)

---

Features
--------

[](#features)

FeatureDescription**Hreflang group CRUD**Every row in `panth_seo_hreflang_group` pairs a canonical Entity Type (`product`, `category` or `cms_page`), Group Code (admin-only identifier), Notes (free-text context) and Active flag. Deactivating a group stops its tags from rendering on the next request without deleting the data — useful for staging hreflang work or quickly backing out a bad mapping.**Members editor**`panth_seo_hreflang_member` rows are edited inline on the group form via a `dynamicRows` UI component. Each row holds Store View (FK to `store.store_id`), Entity ID (product / category / cms\_page ID in that store), Locale (optional BCP 47 override), URL (optional absolute URL override) and Is Default (drives `x-default`). Rows can be added, edited, deleted, and round-trip correctly through Save &amp; Continue Edit.**Locale fallback**When a member row's Locale is blank, the resolver reads the store's `general/locale/code`, converts underscore to hyphen (`en_US` → `en-US`), and uses that. So a simple group creation on an existing multi-store install needs zero explicit locale entry — just pick the Store View and Entity ID.**URL auto-resolution**When a member row's URL is blank, the Save controller looks up `url_rewrite` for that entity + store, prepends the store's base URL, and stores the absolute URL. Updates to the entity's URL key are not automatically tracked — re-save the group (or click Save on the relevant group) after a URL rewrite change to refresh the members.**x-default handling**One member per group can be flagged Is Default. That member's URL is emitted as the `x-default` alternate in addition to its locale-specific row, matching Google's [hreflang best practice](https://developers.google.com/search/docs/specialty/international/localized-versions) of always carrying a fallback for users whose locale doesn't match any other entry. When no row is flagged default, the first member's URL is used.**Three CMS matching strategies**CMS pages are special — they often exist under the same identifier across stores, so manual group creation is wasteful. `cms_relation_method = by_url_key` (default) matches CMS pages across stores by their `identifier` column; `by_id` matches by numeric `page_id`; `by_identifier` falls through to the manual group table. Per-store-view configurable.**Per-website or global scope**`hreflang_scope = website` (default) restricts alternates to stores within the same website as the current request. `global` includes every active storefront store regardless of website. Relevant when two independent brands share one Magento install but shouldn't cross-link.**Self-diagnostic**`Model\Hreflang\Diagnostic::runDiagnostics()` runs five checks against the live DB every time the config page is loaded — x-default coverage, group size, store locale configuration, locale conflicts inside groups, hreflang-enabled status of each member's store — and renders the results inline on the config page. Errors flag real problems; warnings flag best-practice deviations.**Entity finder modal**The edit form has a Browse Products / Browse Categories / Browse CMS Pages toolbar. Each button opens a searchable modal (matches by name / SKU / identifier / numeric ID) and copies the clicked entity's ID to the clipboard with a quick amber flash. The buttons dim when they don't match the group's Entity Type — no browsing categories for a product-typed group.**Theme-agnostic storefront**`ViewModel\Hreflang` computes alternates once per request. `view/frontend/layout/default.xml` attaches the head block to the `head.additional` reference container, so the exact same `` tags ship on Hyva, Luma, and any custom theme — no template overrides, no theme-specific JS, no Alpine / RequireJS integration needed.**Accurate entity detection**The ViewModel detects the current entity via registry (`current_product` / `current_category`) first, falling back to `full_action_name` matching for CMS pages (`cms_index_index` reads the home page identifier from store config; `cms_page_view` reads `page_id` from the request). The core `cms_page` registry key is only populated by the admin edit controller — using it on the storefront would miss every request, so we don't.**Active-flag enforcement**The resolver joins `panth_seo_hreflang_group` on the member lookup and filters `is_active = 1`. Flipping a group to Active = No in the grid immediately hides its tags on the next request.**Same-locale deduplication**When two stores share a locale (e.g. two USD-denominated stores both using `en_US`), emitting duplicate hreflang entries would confuse crawlers. The resolver detects `
