Title: AMP WP &#8211; Google AMP For WordPress
Author: Pixelative
Published: <strong>September 17, 2018</strong>
Last modified: May 11, 2026

---

Search plugins

![](https://ps.w.org/amp-wp/assets/banner-772x250.png?rev=1946984)

![](https://ps.w.org/amp-wp/assets/icon-256x256.png?rev=2552940)

# AMP WP – Google AMP For WordPress

 By [Pixelative](https://profiles.wordpress.org/pixelative/)

[Download](https://downloads.wordpress.org/plugin/amp-wp.1.7.6.zip)

 * [Details](https://wordpress.org/plugins/amp-wp/#description)
 * [Reviews](https://wordpress.org/plugins/amp-wp/#reviews)
 * [Development](https://wordpress.org/plugins/amp-wp/#developers)

 [Support](https://wordpress.org/support/plugin/amp-wp/)

## Description

**AMP WP** is the most feature-rich, developer-friendly, and beginner-ready Google
AMP plugin available for WordPress, completely free.

Originally built by **[Pixelative](https://pixelative.co)**, a professional web 
development agency, AMP WP is now independently developed and maintained by **[Mohsin Rafique](https://mohsinrafique.com)**,
the lead engineer behind the plugin since its inception. AMP WP has helped thousands
of website owners dramatically improve mobile page speed, search rankings, and user
experience.

[Online Demo](https://pixelspress.com/amp) | [CF7 Premium Extension](https://1c8979da.sibforms.com/serve/MUIFAPfaW_zG5aVJNBG78I1qIu30utV8kT5_ERiosqVMstRk9Nj1o6RVbEbyaJkvyZ9TQ3b79YDkpPjsyd99NmbxAlNtZQrx9TkcFAF3V6DvgcoiCcnaZkgvPxl_OpctNUzI-G7xDKxwMq2d2Cm2RteW4LoOxEi-XMmdvhfCiMDxfBsOx18Pd9U1xsTcOqIdyT9WccheL83rrsCeeQ==)
| [Support](https://wordpress.org/plugins/amp-wp/mohsin.rafique@gmail.com?output_format=md)

### Why AMP WP?

Google’s Accelerated Mobile Pages (AMP) technology delivers pages up to **5x faster**
on mobile devices. Faster pages mean lower bounce rates, higher engagement, and 
better rankings in Google Search. AMP WP makes enabling AMP on your WordPress site
effortless, from a single settings panel with no theme modifications needed.

### Free Features

**Performance & Compatibility**
 * Full Google AMP specification compliance (100%
valid AMP output) * PHP 8.x compatible (tested through PHP 8.4) * Compatible with
all major caching plugins (WP Rocket, SG Optimizer, W3 Total Cache, and more) * 
Compatible with Jetpack * Compatible with Yoast SEO (100%) * Compatible with “Automattic
AMP” plugin * Gutenberg block editor support * RTL language support (100%) * GDPR
compliant

**Content & Embeds**
 * Automatic AMP conversion for Posts, Pages, and Custom Post
Types * Embed Images, Videos, Audios, and iFrames: YouTube, Vimeo, Twitter, Facebook,
SoundCloud, Instagram (Posts, Reels & TV) * Lightbox for Images * Slider Support*
Internal AMP Linking * Native AMP Search

**Design & Customization**
 * Two listing layouts: Classic View and List View * 
Customizable color scheme * Custom CSS options * Sticky Header * AMP WordPress Navigation
Menu * Custom AMP Front Page * Social Icons

**Control**
 * Show/Hide AMP for individual Posts, Pages, and Custom Post Types *
Show/Hide AMP for Taxonomies (Categories, Tags, Custom) * Show/Hide AMP mobile redirections*
Show/Hide AMP on Search pages * Show/Hide Date, Author, and Thumbnail across Archive,
Single Post, Related Posts, and Slider * Show/Hide Tags on Single Post pages * Enable/
Disable Structured Data (JSON-LD Schema)

**Engagement & Analytics**
 * Related Posts (with thumbnail, date, and author controls)*
Recent Comments * Notice Bar * Sidebar * Social Sharing Buttons * OneSignal Push
Notifications integration * Third-party analytics support: Google Analytics, Facebook
Pixel, Segment, Quantcast, Alexa Metrics, Chartbeat, comScore, Yandex Metrica, AFS
Analytics, Adobe Analytics

**Ads**
 * Google AdSense Auto Ads for AMP support

**Multilingual**
 * Translation Panel included * Contact us at `mohsin.rafique@gmail.
com` to contribute translations

### Maintained by Mohsin Rafique

AMP WP was originally created by **[Pixelative](https://pixelative.co)**, a full-
service digital agency specializing in high-performance WordPress solutions, and
remains under Pixelative’s ownership. The plugin is currently developed, updated,
and supported independently by **Mohsin Rafique**, a seasoned WordPress engineer
with deep expertise in AMP specification compliance, PHP performance, and modern
web standards.

For support, custom AMP theme development, or white-label licensing, contact **Mohsin
Rafique** at [mohsinrafique.com](https://mohsinrafique.com) or [mohsin.rafique@gmail.com](https://wordpress.org/plugins/amp-wp/mohsin.rafique@gmail.com?output_format=md).

#### Credits

 * [WordPress Plugin Boilerplate Generator](https://wppb.me/) by Tom McFarlin, License:
   GPLv2
 * [normalize.css](http://necolas.github.io/normalize.css/), License: MIT
 * [Karla](https://fonts.google.com/specimen/Karla) by Jonathan Pinhorn, License:
   SIL OFL
 * [Noto Sans](https://fonts.google.com/specimen/Noto+Sans) by Google, License: 
   SIL OFL
 * [Overpass Mono](https://fonts.google.com/specimen/Overpass+Mono) by Delve Withrington,
   License: SIL OFL
 * [Font Awesome Free 6.7.2](https://fontawesome.com/license) by Fonticons, Inc.,
   Font: SIL OFL 1.1 / Code: MIT

### Minimum Requirements

 * WordPress 5.0 or higher
 * PHP 7.4 or higher
 * MySQL 8.0+ or MariaDB 10.5+

**Tip:** Install [Regenerate Thumbnails](https://wordpress.org/plugins/regenerate-thumbnails/)
and regenerate your thumbnails after activation to ensure the post listing layout
renders correctly.

### Automatic Installation (Recommended)

 1. Log in to your WordPress admin panel.
 2. Navigate to **Plugins -> Add New**.
 3. Search for **AMP WP**.
 4. Click **Install Now**, then **Activate**.
 5. Go to **AMP WP -> Customize AMP** to configure your settings.

### Manual Installation

 1. Download the plugin ZIP from the WordPress plugin repository.
 2. Extract the ZIP and upload the `amp-wp` folder to `/wp-content/plugins/` via FTP
    or your hosting file manager.
 3. Activate the plugin from **Plugins** in your WordPress admin panel.
 4. Navigate to **AMP WP -> Customize AMP** to begin setup.

### Developer Hooks

AMP WP exposes WordPress-standard actions and filters throughout its template system,
URL generator, structured data engine, and admin panel. All hooks listed here are
safe to use in a child theme’s `functions.php` or in a standalone plugin. No plugin
file edits are needed.

#### Template Actions

These actions fire inside AMP WP’s own template system. They do not use `wp_head`
or `wp_footer`. Output must be valid AMP markup.

**`amp_wp_template_head`**
 Fires inside the AMP `<head>` element. Use for custom
meta tags or other head markup. AMP WP reserves priority 0 for component scripts.

**`amp_wp_template_head_deferred`**
 Fires in `<head>` after the AMP boilerplate
styles have been written. Required injection point for `<amp-auto-ads>` and any 
snippet that must follow the boilerplate. AMP WP’s own styles and scripts output
here.

**`amp_wp_template_body_start`**
 Fires immediately after the opening `<body>` tag.

**`amp_wp_body_beginning`**
 Fires at the start of visible body content, before 
the site header renders.

**`amp_wp_post_content_below`**
 Fires directly below the post content on single
post pages.

**`amp_wp_template_footer`**
 Fires before the closing `</body>` tag. Priority 999
is reserved for AMP WP’s output sanitizer.

**`amp_wp_template_enqueue_scripts`**
 Use to register additional AMP component 
scripts. Call `amp_wp_enqueue_script( $handle, $src )` inside your callback.

**`amp_wp_after_comment_list`**
 Fires after the comment list on single post pages.

**`amp_wp_notifications_bar`**
 Fires inside the notification/notice bar template
slot.

**`amp_wp_gdpr_compliance`**
 Fires inside the GDPR banner template slot.

#### Analytics Actions

These actions fire in the AMP page footer. Each corresponds to one analytics provider
already supported by AMP WP. Hook into any of them to append a custom `<amp-analytics
>` block for a provider not yet built in, or to modify the existing output before
it renders.

 * `amp_wp_analytics_ga` (Google Analytics)
 * `amp_wp_analytics_fbp` (Facebook Pixel)
 * `amp_wp_analytics_sa` (Simple Analytics)
 * `amp_wp_analytics_qc` (Quantcast)
 * `amp_wp_analytics_acm` (Adobe Campaign Manager)
 * `amp_wp_analytics_cb` (Chartbeat)
 * `amp_wp_analytics_comscore` (comScore)
 * `amp_wp_analytics_yandex_metrica` (Yandex Metrica)
 * `amp_wp_analytics_afs` (AFS Analytics)
 * `amp_wp_analytics_adobe` (Adobe Analytics)

#### AMP Version Control Filters

**`amp_wp_amp_version_exists`**
 Control whether an AMP version is served for the
current request. Return `false` to disable AMP for that page. Parameter: `(bool)
$exists`

    ```
    add_filter( 'amp_wp_amp_version_exists', '__return_false' );
    ```

**`amp_wp_template_auto_redirect`**
 Enable automatic redirection of all visitors
from the non-AMP URL to the AMP URL. Default `false`. Parameter: `(bool) $redirect`

**`amp_wp_filter_config_list`**
 Extend the list of post types, taxonomies, and 
conditions where AMP is disabled site-wide. Parameter: `(array) $filters`

#### URL and Permalink Filters

**`amp_wp_pre_get_permalink`**
 Short-circuit AMP permalink generation. Return any
non-false value to bypass the core URL builder. Parameters: `(mixed) $pre` (default
false), `(int) $post_id`

**`amp_wp_get_permalink`**
 Filter the final AMP URL after it has been built. Parameters:`(
string) $amp_url`, `(int) $post_id`

**`amp_wp_url_format_filter`**
 Change the AMP URL format. Accepted values: `start-
point` (prefix, e.g. `/amp/slug`) or `end-point` (suffix, e.g. `/slug/amp`). Parameter:`(
string) $format`

**`amp_wp_url_excluded`**
 Add URL paths that must never serve an AMP version. Parameter:`(
array) $excluded_urls`

**`amp_wp_transformer_exclude_subdir`**
 Add path segments that the AMP URL transformer
should skip when rewriting internal links. Used internally by AMP WP for WPML and
Polylang language prefixes. Parameter: `(array) $exclude_dirs`

#### Structured Data Filters (JSON-LD)

All JSON-LD filters are active only when “Enable Structured Data on Site” is on 
in AMP WP Settings. The three schema-data filters carry a trailing underscore. This
is generated internally via `sprintf( 'amp_wp_json_ld_%s_', $type )` and the underscore
must be part of the hook name you register.

**`amp_wp_json_ld_config`**
 Filters the generator configuration before any schema
is built.

Parameter: `(array) $config` with keys:
 * `active` (bool): set `false` to disable
the entire JSON-LD generator for the current request. * `logo` (string): Organization
logo URL. When non-empty, an `Organization` block is emitted on every page and all
Article-type schemas reference it by `@id`. * `posts_type` (string): Fallback schema
type when `schema_type_for_post` is empty. Default `BlogPosting`. * `media_field_id`(
string): Post meta key for audio/video URL in format posts. Default `_featured_embed_code`.

AMP WP core attaches at priority 15 to inject the branding logo. Use priority 20
or higher to override it.

    ```
    add_filter( 'amp_wp_json_ld_config', function( $config ) { ... }, 20 );
    ```

**`amp_wp_json_ld_organization_`**
 Filters the `Organization` schema array before
output. Fires only when a logo is configured. Return `false` or an empty array to
suppress the block. Parameter: `(array) $data`

    ```
    add_filter( 'amp_wp_json_ld_organization_', function( $data ) { ... } );
    ```

**`amp_wp_json_ld_website_`**
 Filters the `WebSite` schema array before output.
Fires only on the homepage and front page. Parameter: `(array) $data`

    ```
    add_filter( 'amp_wp_json_ld_website_', function( $data ) { ... } );
    ```

**`amp_wp_json_ld_single_`**
 Filters the singular-content schema array before output.
Fires on all singular pages: standard posts (Article, NewsArticle, BlogPosting),
static pages (WebPage), WooCommerce products (Product), post format overrides (AudioObject,
VideoObject, ImageObject), and custom post types. Parameter: `(array) $data`

    ```
    add_filter( 'amp_wp_json_ld_single_', function( $data ) { ... } );
    ```

#### Content and Theme Filters

**`amp_wp_template_page_on_front`**
 Specify the page ID to use as the AMP front
page when a static homepage is configured. Parameter: `(int) $page_id`, default 
0.

**`amp_wp_template_show_on_front`**
 Control what displays on the AMP homepage. 
Accepted values: `posts` or `page`. Parameter: `(string) $show_on_front`

**`amp_wp_template_active_template`**
 Override the active template metadata array.
Parameter: `(array) $template_info`

**`amp_wp_template_set_menu_walker`**
 Enable or disable the custom sidebar menu
walker for a specific nav menu location. Parameters: `(bool) $use_walker`, `(array)
$args`

**`amp-wp-template-default-theme-mod`**
 Set default values for AMP WP Customizer
options. Parameters: `(mixed) $default_value`, `(string) $option_key`

**`amp_wp_home_featured`**
 Customize the `WP_Query` arguments used to fetch posts
for the homepage featured slider. Parameter: `(array) $query_args`

**`amp_wp_get_template`**
 Override the file path used to locate a template part.
Parameters: `(string) $located`, `(string) $file`, `(array) $args`, `(string) $template_path`,`(
string) $default_path`

**`amp_wp_html_dom_filter_attributes`**
 Filter an HTML element’s attributes during
the DOM processing pipeline. Parameters: `(array) $attributes`, `(string) $tag_name`,`(
array) $valid_attributes`

**`amp_wp_style_files_{$file}`**
 Filter CSS file content before it is added to 
the inline `<style amp-custom>` block. `{$file}` is the stylesheet handle. Parameter:`(
string) $css`

**`amp_wp_social_share_cache_time`**
 Set the cache duration in seconds for social
share counts. Default 7200 (120 minutes). Parameters: `(int) $seconds`, `(int) $
post_id`

**`amp_wp_social_share_count`**
 Filter social share count results after they are
fetched. Parameter: `(array) $results`

**`amp_wp_gdpr_country_list`**
 Customize the list of countries considered GDPR-
compliant. Parameter: `(array) $countries`

**`amp_wp_translation_std`**
 Provide or override fallback translation strings. 
Parameter: `(array) $translations`

#### Admin and Settings Hooks

**`amp_wp_settings_tab_menus`** (filter)
 Add a custom tab to the AMP WP settings
panel. Key is the tab slug, value is the tab label HTML. Parameter: `(array) $tabs`

    ```
    add_filter( 'amp_wp_settings_tab_menus', function( $tabs ) { $tabs['my-tab'] = '<span>My Tab</span>'; return $tabs; } );
    ```

**`amp_wp_settings_tab_section`** (action)
 Render the HTML content for your custom
settings tab. Check `$_GET['tab']` to target a specific tab.

**`amp_wp_save_setting_sections`** (action)
 Fires when the settings form is submitted.
Hook here to read and save data for a custom tab.

**`amp_wp_save_setting_notice`** (filter)
 Customize the “Settings saved.” notice
text. Parameter: `(string) $notice_text`

**`amp_wp_welcome_tab_menus`** (filter)
 Add a custom tab to the AMP WP welcome/
dashboard page. Parameter: `(array) $tabs`

**`amp_wp_welcome_tab_section`** (action)
 Render HTML content for a custom welcome
page tab.

**`amp_wp_default_configurations`** (action)
 Fires on plugin activation. Hook here
to set default options for add-on plugins.

## Screenshots

 * [[
 * Home Page
 * [[
 * Single Post Page
 * [[
 * Tags, Social Icons, Related Posts, Comments, and Footer
 * [[
 * Search & Archive Page
 * [[
 * 100% Valid AMP Content
 * [[
 * AMP WP Options Panel
 * [[
 * AMP Auto Ads Support
 * [[
 * Compatible with Major Cache Plugins
 * [[
 * Embed Images, Videos, Audios & iFrames
 * [[
 * Toggle Search & Header
 * [[
 * Recent Comments
 * [[
 * Sidebar, Social Icons & Related Posts
 * [[
 * Core WordPress Customizer Integration
 * [[
 * AMP WP Settings Panel

## FAQ

### What is the URL structure for AMP pages?

AMP WP supports two URL formats:

 1. **Prefix format:** `https://yoursite.com/amp/page-name`
 2. **Suffix format:** `https://yoursite.com/page-name/amp`

You can choose your preferred format from **AMP WP -> Settings -> General**.

### How do I add analytics tracking?

Go to **AMP WP -> Settings -> Analytics** in your WordPress admin dashboard. AMP
WP supports Google Analytics, Facebook Pixel, Segment, Quantcast, Alexa Metrics,
Chartbeat, comScore, Yandex Metrica, AFS Analytics, and Adobe Analytics.

### The post listing layout looks broken: how do I fix it?

This is usually caused by inconsistent thumbnail sizes. Install and run [Regenerate Thumbnails](https://wordpress.org/plugins/regenerate-thumbnails/)
to normalize all image sizes.

### Does AMP WP support Instagram Reels and TV posts?

Yes. Since version 1.6.0, AMP WP supports Instagram `/p/`, `/reel/`, and `/tv/` 
post types natively via `amp-instagram`.

### What prebuilt listing layouts are available?

Two layouts are included: **Classic View** and **List View**. Switch between them
from **AMP WP -> Options Panel**.

### How do I inject custom HTML (e.g., ad codes, analytics snippets)?

Go to **Dashboard -> AMP WP -> Customize AMP**. You can inject valid AMP snippets:
*
Between `<head></head>` tags * Right after the `<body>` opening tag * Right before
the `</body>` closing tag

Only valid, AMP-compatible code will function on AMP pages.

### How do I enable AdSense Auto Ads for AMP?

Navigate to **Dashboard -> AMP WP -> Customize AMP**. Paste your Auto Ads code in
the `<head>` and right after `<body>` fields.

[AdSense Auto Ads for AMP – Google Help](https://support.google.com/adsense/answer/9011465)

### How do I enable or disable AMP for a specific post?

Edit the post in WordPress, scroll to the **AMP WP** meta box in the sidebar, and
toggle the AMP option on or off for that individual post.

### How do I report a bug or request a feature?

Please email `mohsin.rafique@gmail.com` or open a thread on the [WordPress support forum](https://wordpress.org/support/plugin/amp-wp/).

## Reviews

![](https://secure.gravatar.com/avatar/61f23dcc83a55eee501ecc2ebd9931032170542bd1889f8b5fd52fa108148c42?
s=60&d=retro&r=g)

### 󠀁[Лучший плагин](https://wordpress.org/support/topic/%d0%bb%d1%83%d1%87%d1%88%d0%b8%d0%b9-%d0%bf%d0%bb%d0%b0%d0%b3%d0%b8%d0%bd-26/)󠁿

 [newsroyals](https://profiles.wordpress.org/newsroyals/) July 31, 2022

Этой самый простой и лучший плагин AMP, который я пробовала. Если бы еще добавить
поддержку рекламных блоков – цены бы ему не было.

![](https://secure.gravatar.com/avatar/1cb548dfa82cb501a9ca412c91e5ec88fd4028ff6b52419d34fb8924a2e85749?
s=60&d=retro&r=g)

### 󠀁[Fast and easy plugin](https://wordpress.org/support/topic/fast-and-easy-plugin-3/)󠁿

 [lash](https://profiles.wordpress.org/ranc007/) June 21, 2022

Fast and easy plugin

![](https://secure.gravatar.com/avatar/f4b639c2c826265120c82e4a9bfe387b41f78095046f0d91da0664a90e42e54d?
s=60&d=retro&r=g)

### 󠀁[Works fine!](https://wordpress.org/support/topic/works-fine-1416/)󠁿

 [bf339](https://profiles.wordpress.org/bf339/) April 5, 2022

Fast settings for getting working page!

![](https://secure.gravatar.com/avatar/784be2e4e6252d029377690d26af0350bb4b4fdcdef281df6a26aeeacc233eb7?
s=60&d=retro&r=g)

### 󠀁[70](https://wordpress.org/support/topic/70-20/)󠁿

 [Adamu](https://profiles.wordpress.org/adamushuaibu/) March 17, 2022

Our photos

![](https://secure.gravatar.com/avatar/aade1543ffdc31e92868567231d599b9e8eecc60a13266af2a8148c8eb49e934?
s=60&d=retro&r=g)

### 󠀁[Works out of the box as advertised](https://wordpress.org/support/topic/works-out-of-the-box-as-advertised/)󠁿

 [docrpp](https://profiles.wordpress.org/docrpp/) March 10, 2022

Works out of the box. Just enough features for my use case. Two suggestions: 1. 
Would be nice to have a performance option: to enable server-side cache for amp 
pages specifically at the plugin level 2. Need an option to add “view desktop version”
to the header as well.

![](https://secure.gravatar.com/avatar/d56575991f929c2d92b5b1f17b5cc37ca934f6050ed75757426ca45be361e46d?
s=60&d=retro&r=g)

### 󠀁[Total abandon of support](https://wordpress.org/support/topic/total-abandon-of-support/)󠁿

 [jessik](https://profiles.wordpress.org/jessik/) February 16, 2022

The extension works better than the other AMP ones and is way more customizable.
However, the authors don’t bother answering to questions on the forum. Most of the
topics sat unsolved for more than 6 months. Just for that, it deserves a 2 star 
rating. You can’t just put a plugin out there and be like: “ok do your thing now,
not concerned anymore, bye”

 [ Read all 56 reviews ](https://wordpress.org/support/plugin/amp-wp/reviews/)

## Contributors & Developers

“AMP WP – Google AMP For WordPress” is open source software. The following people
have contributed to this plugin.

Contributors

 *   [ Pixelative ](https://profiles.wordpress.org/pixelative/)
 *   [ Mohsin Rafique ](https://profiles.wordpress.org/mohsinrafique/)

[Translate “AMP WP – Google AMP For WordPress” into your language.](https://translate.wordpress.org/projects/wp-plugins/amp-wp)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/amp-wp/), check out
the [SVN repository](https://plugins.svn.wordpress.org/amp-wp/), or subscribe to
the [development log](https://plugins.trac.wordpress.org/log/amp-wp/) by [RSS](https://plugins.trac.wordpress.org/log/amp-wp/?limit=100&mode=stop_on_copy&format=rss).

## Changelog

#### Unreleased

#### 1.7.6 – 2026-05-12

**Security**

 * Comprehensive WordPress Coding Standards security sweep across the entire plugin.
   Output escaping (`esc_html`, `esc_attr`, `esc_url`, `wp_kses`, `wp_kses_post`)
   applied to every flagged `echo` / `printf` site in admin partials, settings forms,
   public templates, customizer controls, and core functions. Superglobal reads (`
   $_SERVER['REQUEST_URI']`, `$_SERVER['SCRIPT_FILENAME']`, `$_SERVER['PHP_SELF']`,`
   $_SERVER['HTTP_USER_AGENT']`, `$_SERVER['SERVER_SOFTWARE']`, `$_SERVER['LOCAL_ADDR']`,`
   $_SERVER['SERVER_ADDR']`) now consistently guarded with `isset()` and run through`
   esc_url_raw( wp_unslash() )` or `sanitize_text_field( wp_unslash() )` as appropriate
   per use site. Translation strings with intentional HTML (e.g. `<strong>` for 
   inline emphasis) now route through `wp_kses_post( __() )` instead of bare `_e()`
   so the markup is preserved while bot-injected HTML is filtered out. Legacy `//
   WPCS: XSS ok.` comments replaced with modern `// phpcs:ignore WordPress.Security.
   EscapeOutput.OutputNotEscaped --` annotations with a one-line justification each.
   Net effect: the `WordPress.Security.EscapeOutput`, `WordPress.Security.NonceVerification`,
   and `WordPress.Security.ValidatedSanitizedInput` sniffs report 0 errors and 0
   warnings across the plugin (down from 311 errors before the sweep). Total WPCS
   reduction: 1,448 -> 632 (56%). No behavioural change – all edits are escaping/
   sanitizing additions or `phpcs:ignore` annotations on canonical safe-output patterns.

**Added**

 * New “Premium Extensions” tab on the AMP WP Settings page (`admin.php?page=amp-
   wp-settings#settings-premium-extensions`). Central admin home for AMP WP family
   add-ons that need configurable settings without forking a full settings tab. 
   Add-ons populate the tab via the new `amp_wp_premium_extensions_section` action–
   callbacks echo a card (heading + `form-table` row group) inside the tab body,
   and the existing `amp_wp_save_setting_sections` action persists each add-on’s
   option independently. New files: `includes/admin/settings/class-amp-wp-premium-
   extensions.php` (registers the tab) and `admin/partials/settings/amp-wp-admin-
   premium-extensions.php` (the form scaffold).
 * Premium-extension registration API: `amp_wp_register_premium_extension( string
   $slug, array $args = [] ): void`, `amp_wp_get_registered_premium_extensions():
   array<string,array<string,string>>`, and `amp_wp_has_active_premium_extension():
   bool` (all in `includes/functions/amp-wp-core-functions.php`). Each AMP WP family
   add-on self-registers once on bootstrap with a slug + display metadata (`name`,`
   description`, `version`, `url`). Idempotent: registering the same slug twice 
   is a no-op. New companion filter `amp_wp_premium_extensions` for advanced reordering,
   suppression, or unit-test snapshot/restore. The empty-state partial reads the
   registry to render the active-extensions list (instead of hard-coding “AMP WP–
   Contact Form 7”).
 * Template-path registration: new public functions `amp_wp_register_template_path(
   string $absolute_path ): void` and `amp_wp_get_registered_template_paths(): array`(
   in `includes/functions/amp-wp-theme-functions.php`) let AMP WP family add-ons
   ship their own AMP templates instead of having them live inside core’s “Tez” 
   theme directory. Resolution order is `<wp-theme>/amp-wp/<template>` (site override–
   unchanged) -> registered add-on paths in registration order -> core’s Tez directory
   as the catch-all fallback. End-user override convention preserved verbatim. New
   filter `amp_wp_template_paths` lets advanced users reorder or suppress paths 
   per-request. See ADR-002. Companion change in `amp-wp-woocommerce` migrates eight
   WC-specific AMP partials out of core to restore the isolation rule “Core never
   references any add-on by name”.
 * New extension hook `amp_wp_layout_setting_after_show_comments` fires inside the
   Layout Settings -> Single Post Page table, immediately after the “Show Comments”`
   <tr>`. Designed for AMP WP family add-ons (e.g. AMP WP – Comments uses it to 
   print a “Show Comment Replies” toggle row) to extend the comment-related settings
   block without forking `admin/partials/settings/amp-wp-admin-layout.php`. Callbacks
   must echo a complete `<tr>...</tr>` matching the surrounding form-table markup;
   inputs may piggyback on the existing `amp_wp_layout_settings[...]` name prefix
   to persist via the existing save handler at `Amp_WP_Layout::amp_wp_save_layout_settings()`–
   no separate option, no separate save flow.

**Changed**

 * The “Premium Extensions” tab is now hidden by default – it only registers when
   at least one AMP WP family add-on (CF7, Comments, WooCommerce, WPForms, Gravity
   Forms, Ads Manager) has called the new `amp_wp_register_premium_extension()` 
   function on its bootstrap. Previously the tab appeared on every install, even
   on a fresh one with no add-ons active, where it rendered an empty-state hint.
   Back-compat fallback: if an older add-on hooks `amp_wp_premium_extensions_section`
   directly without registering, the action presence still triggers the tab. Both
   the tab definition and the partial loader gate on the same check, so a stale 
   anchor link to `#settings-premium-extensions` no longer paints orphaned form 
   markup either.

**Fixed**

 * Browsers fetching `/favicon.ico` (and any other root-level static-file URL) on
   mobile no longer trigger a 404. `Amp_WP_Public::amp_wp_auto_redirect_to_amp()`
   fed `$_SERVER['REQUEST_URI']` through `Amp_WP_Content_Sanitizer::transform_to_amp_url()`,
   which blindly appended `/amp` to any internal URL it didn’t already recognise
   as an AMP path or wp-content asset. When a site has no static `favicon.ico` file
   at the document root, the browser-issued favicon request fell through to `index.
   php`, hit `template_redirect` on mobile, and the auto-redirect bounced the browser
   to `/favicon.ico/amp` – which never matches a rewrite rule and 404s. Same shape
   would fire for any root-level static file (`sitemap.xml`, `robots.txt`, `ads.
   txt`, `manifest.json`, etc.) when no physical file exists. Fix: `transform_to_amp_url()`
   now short-circuits and returns the URL unchanged when the path’s basename has
   a static-file extension (35-entry list covering icons, images, scripts, styles,
   fonts, archives, media, metadata). List is filterable via the new `amp_wp_non_amp_url_extensions`
   filter so unusual extensions can be added per-site. Case-insensitive match. Side
   benefit: every other call site of `transform_to_amp_url()` – filters on `term_link`,`
   author_link`, `attachment_link`, `post_type_link`, the nav-menu `href` filter,
   the canonical-URL helper – is now also protected from inadvertently rewriting
   static-file URLs that themes or third-party plugins happen to pass through them.
 * Search-engine crawlers no longer get caught by the mobile auto-redirect to AMP.`
   Amp_WP_Public::amp_wp_auto_redirect_to_amp()` previously checked only `wp_is_mobile()`,
   which returns true for Googlebot-Mobile, Bingbot, YandexBot, DuckDuckBot, AppleBot,
   FacebookExternalHit, Twitterbot, LinkedInBot, Slurp, AhrefsBot, and SemrushBot.
   Each was being 302-redirected from `https://yoursite.com/` to `https://yoursite.
   com/amp/`; the AMP page’s `<link rel="canonical">` then pointed back at the original,
   and Google Search Console flagged the canonical URL as “Redirect error” in Page
   Indexing because the URL it was trying to index kept redirecting. Google’s AMP
   guidelines explicitly require the canonical to be served directly to bots; AMP
   discovery happens via the head-tag `<link rel="amphtml">`, not a UA redirect.
   Fix: new public helper `amp_wp_is_search_engine_bot(): bool` in `includes/functions/
   amp-wp-core-functions.php` checks `HTTP_USER_AGENT` against a 12-entry list (
   substring match, case-insensitive); the redirect path bails early when it returns
   true. The cache-plugin desktop fallback (which injects the UA-sniffing JS redirect)
   is implicitly safe because the server-side branch already short-circuited for
   bots. Filterable via `amp_wp_search_engine_bot_user_agents` (UA fragment list)
   and `amp_wp_is_search_engine_bot` (final boolean). Unit-tested against 10 real-
   world UA strings (7 bots + 3 real users) – 10/10 pass. After the fix ships, click“
   Validate fix” inside Search Console; Google re-crawls the affected URLs in 1-
   7 days and the “Redirect error” count drops to 0.
 * Pagination on AMP archives was broken for any URL of the form `/<archive>/amp/
   page/N/`. The URL-based branch of `is_amp_wp()` (used during `pre_get_posts` 
   before `template_redirect` fires, when the `amp` query var is not yet set on `
   $wp_query`) only matched the AMP token at the very start or very end of the request
   URI – so `/shop/amp/page/2/`, `/product-category/<slug>/amp/page/2/`, `/category/
   <slug>/amp/page/2/`, `/tag/<slug>/amp/page/2/`, and `/<page>/amp/comment-page-
   N/` all returned `false`. The cascade was severe: any third-party `pre_get_posts`
   callback gated on `is_amp_wp()` (notably the AMP WP – WooCommerce add-on’s priority-
   0 bridge that re-registers `WC_Query::pre_get_posts` at priority 101) bailed 
   early, AMP WP’s query isolation between priorities 1 and 100 wiped WooCommerce’s
   product-archive setup, and `/shop/amp/page/2/` rendered the shop _page_ (post
   type `page`, ID 588) with `paged=2` instead of the products grid. The old second
   regex also had a separate false-positive bug where `amp/*` allowed zero trailing
   characters and matched URIs like `/ampersand/` and `/amp-tree/`. Both regexes
   replaced with a single boundary-anchored pattern `#(?:^|/)<amp>(?:/|$)#` that
   detects AMP as a whole path segment anywhere in the URI; verified against 20 
   URL patterns (20/20 pass) including paginated archives, sub-directory installs,
   and the previously-broken false positives. Live verification on `/shop/amp/page/
   2/`: `post_count=8 found_posts=50 max_num_pages=7 paged=2 post_type=product is_archive
   =1 is_post_type_archive=1 is_amp_wp=1 is_shop=1 is_woocommerce=1` (was `post_count
   =1 paged=2 post_type="" is_archive=0 is_page=1 is_amp_wp=0` before the fix).
 * The “Premium Extensions” tab was rendering an empty `<i>` tag with no visible
   icon next to the label. The original `amp-wp-admin-icon-star` class did not exist
   in `admin/css/amp-wp-admin.css` or in the icon font at `admin/fonts/amp-wp-admin-
   icons/`. Switched to `amp-wp-admin-icon-feather`, which is defined and not already
   in use by another tab (every star / puzzle / rocket / crown glyph variant is 
   missing or taken). CSS and font are unchanged.

**Docs**

 * Inline help text added to five settings tabs: Structured Data, GDPR Compliance,
   Notice Bar, Layout Settings, and General Settings. Around 30 new `<p class="description"
   >` blocks under every previously-undocumented option so admins do not need to
   consult external docs to know what each toggle / select / textarea does. Highlights:
   the GDPR master toggle now explains the EU/EEA IP gate and the third-party-script
   suppression behaviour; Layout’s “Show Slider on Home Page”, “Show Share Box In
   Posts”, and “Show Related Posts” parent toggles each get a description plus descriptions
   on every sub-control; General’s “Enable AMP on Home Page”, “Enable AMP on Search
   Page”, “Disable AMP on Post Types”, and “Disable AMP on Taxonomies” finally have
   inline guidance. All strings wrapped in `esc_html_e( ..., 'amp-wp' )` using the
   same `<p class="description">` pattern already established by the GDPR partial.
   No PHP / behaviour changes – pure documentation in the admin UI.
 * Inline help text added under the OneSignal options on the 3rd Party Plugins tab(`
   admin.php?page=amp-wp-settings#settings-third-party-plugins-support`). Three 
   new `<p class="description">` blocks: under “App ID” (UUID format and where to
   find it – OneSignal dashboard -> Settings -> Keys & IDs), under “Position” (subscription
   bell placement and when to override the default), and under “Subdomain” in the
   HTTP Site row (OneSignal-hosted HTTPS subdomain like `yoursite.os.tc` that non-
   HTTPS sites need for the push subscription frame; HTTPS sites should leave the
   field blank).

#### 1.7.5 – 2026-05-07

 * Fixed: Mobile browsers no longer get stuck in a “too many redirects” loop on 
   AMP URLs after an admin changes “Exclude AMP by URL” or “Exclude URLs From Auto
   Converting”. Plugin-issued redirects (AMP-router and mobile auto-redirect) now
   downgrade the AMP-excluded redirect from `301 Moved Permanently` to `302 Found`
   and emit `nocache_headers()`, so neither browsers, proxies, nor CDNs can pin 
   a stale redirect direction once the underlying setting flips. The desktop-side
   fallback that injects a JavaScript redirect to the AMP URL when a caching plugin
   is detected now also defines `DONOTCACHEPAGE` and emits no-cache headers, preventing
   cache plugins that do not separate cache by device from serving a desktop response(
   which contains the mobile-UA-sniffing redirect script) to mobile visitors and
   triggering an infinite loop in the mobile browser. Existing affected clients 
   are auto-recovered on their next request to a now-AMP-excluded URL: the AMP-router
   redirect response carries a one-shot `Clear-Site-Data: "cache"` header (HTTPS-
   only, gated by an `amp_wp_cache_cleared` cookie marker so normal HTTP caching
   is preserved on subsequent redirects), which evicts any stale `301` pinned in
   the mobile browser before it follows the redirect. See ADR-001.
 * Fixed: `amp-state` elements are no longer stripped from AMP pages when the AMP
   WP Comments plugin is active. The content sanitizer’s allowed-tag list (`tags-
   list.php`) did not include `amp-state`, causing the element to be silently removed
   during the HTML clean-up pass, which broke the AMP threading state used by the
   comment reply form.
 * Fixed: Per-comment Reply links now appear in threaded comment lists on AMP pages.`
   amp_wp_comment_item()` was not forwarding the `$depth` argument from `wp_list_comments()`
   to the `comment-item.php` template. WordPress 6.8 updated `get_comment_reply_link()`
   to return null when depth is 0, so every reply link resolved to nothing. The 
   function now accepts and passes `$depth` (defaulting to 1).
 * Fixed: Per-comment Reply button now shows the label “Reply” instead of the comment
   form title “Leave a Reply”. The template was pulling from `amp_wp_translation_get('
   comments_reply')`, which returns the form heading. The button now uses `__('Reply','
   amp-wp')` directly.
 * Fixed: AFS Analytics configuration JSON was malformed. Missing commas after `
   websiteid` and `title` properties caused a JSON parse error in the AMP runtime,
   silently disabling analytics on AMP pages when AFS Analytics was configured.
 * Improved: `includes/class-amp-wp-redirect-router.php` brought into WordPress 
   Coding Standards compliance. Added a proper file-level docblock (the previous
   one only documented the class). Sanitized `$_SERVER['REQUEST_URI']` via `isset()`
   + `esc_url_raw( wp_unslash() )` in `redirect_to_amp_url()`. Renamed the singleton
   accessor `Run()` to `run()` to satisfy WPCS snake_case naming; the class is documented
   as not-public in the family’s public API contract, so this rename is internal
   and the single caller in `Amp_WP_Public::define_public_hooks()` was updated. 
   None of the six add-ons (cf7, comments, woocommerce, wpforms, gf, ads-manager)
   reference the class.
 * Improved: `public/class-amp-wp-public.php` brought into WordPress Coding Standards
   compliance. Sanitized and unslashed all `$_SERVER['REQUEST_URI']` and `$_SERVER['
   HTTP_HOST']` reads via `esc_url_raw( wp_unslash() )` / `sanitize_text_field( 
   wp_unslash() )` with `isset()` guards in `redirect_to_start_point_amp()`, `redirect_to_end_point_amp()`,
   and `amp_wp_get_requested_page_url()`. Switched all internal same-origin redirects
   from `wp_redirect()` to `wp_safe_redirect()`. Replaced loose `==` comparisons
   with strict `===` in `amp_wp_transform_post_link_to_amp()`, `amp_wp_init_json_ld()`,
   and `is_amp_excluded_by_url()`; added `true` strict flag to all `in_array()` 
   calls in `amp_version_exists()`. Refactored the empty-body if/elseif assignment-
   in-condition chain in `amp_wp_template_loader()` into an explicit early-return
   ladder that preserves the “first matching template wins” semantics including 
   the static-home-page query override and the attachment-template `prepend_attachment`
   filter removal. Renamed the private helper `_amp_wp_can_call_component_method()`
   to drop the leading underscore (visibility is already encoded in the `private`
   keyword) and removed its unused `&$args` reference parameter; the single internal
   caller was updated to match. Renamed the `$default` parameter on `amp_wp_get_option()`
   to `$default_value` to avoid the PHP reserved-keyword shadow. Filled in 19 missing
   or incomplete `@param` doc-comment lines across 13 methods. Removed three blocks
   of dead commented-out code that the surrounding live code superseded. No public-
   API behaviour change: every method signature exposed to add-ons is preserved.
 * Added: `tools/test-redirects.sh` – a curl-based smoke harness that asserts every
   plugin-issued redirect on a target site behaves the way the no-cache + Clear-
   Site-Data + 302 fix promises. Run it against staging or production before pushing
   a release: `BASE_URL=https://your-site.com ./tools/test-redirects.sh`. Covers
   eight scenarios (fresh AMP-excluded redirect, cookie-gated re-request, desktop
   UA, full chain termination, AMP-included single post, mobile auto-redirect cache
   headers, query-string preservation, paginated AMP URL) with 29 individual assertions
   including 302 status, `Cache-Control: no-cache` + `no-store`, `Clear-Site-Data:"
   cache"` presence/absence per cookie state, hardened `Set-Cookie` flags (Secure/
   HttpOnly / SameSite=Lax), Location target, and AMP markers in served bodies. 
   Configurable per site via env vars (BASE_URL, AMP_EXCLUDED_URL, AMP_INCLUDED_URL,
   NON_AMP_URL, PAGINATED_AMP_URL). Exits 0 on green, 1 on any failure with a list
   of failed assertions.

#### 1.7.4 – 2026-05-01

 * Fixed: Header and sidebar logo image no longer disappears when a logo is set 
   in AMP WP branding settings. The v1.7.2 PHPCS escaping pass wrapped the logo 
   output in `wp_kses_post()`, which strips non-standard HTML elements including`
   <amp-img>` and `<amp-anim>`. The logo tag was silently removed on every page 
   load, leaving an empty link in the header. A dedicated `amp_wp_kses_amp_img()`
   helper now sanitizes logo output using `wp_kses()` with `amp-img` and `amp-anim`
   added to the allowed-tag list, preserving `src`, `width`, `height`, `class`, `
   alt`, `sizes`, `layout`, and `on` attributes.
 * Improved: AMP WP meta box in the post/page editor sidebar rebuilt with a professional
   toggle switch UI. The meta box is now pinned to the top of the sidebar panel (
   priority high), the reorder controls are hidden, the panel heading inherits WordPress
   default weight to match Categories and Tags, and the Disable AMP control uses
   a pure-CSS toggle with a red active state and an AMP WP Settings shortcut link
   in the footer.
 * Fixed: Notice Bar and GDPR Compliance no longer silently fail to appear on AMP
   pages. Both save functions stored the enabled switch as integer `1` while the
   frontend callbacks checked for string `'1'` with strict `===` comparison, causing
   the condition to always evaluate false and neither component to render regardless
   of the saved setting.
 * Fixed: Notice Bar settings form was missing nonce verification in the save handler,
   allowing settings to be written without a valid nonce. The form nonce field is
   now aligned with the shared `amp_wp_settings_nonce` token used across all settings
   tabs, and the save function validates it before processing POST data.
 * Fixed: Notice Bar accept button text field incorrectly fell back to an empty `
   array()` instead of an empty string when no value was saved, causing a type mismatch
   when the value was passed to `esc_attr()`.
 * Fixed: GDPR `wp_dropdown_pages()` arguments `show_option_no_change` and `option_none_value`
   were explicitly set to `null`, overriding WordPress defaults and generating PHP
   8 type deprecation warnings. Both are now set to empty strings.
 * Fixed: GDPR consent form accept and reject actions no longer silently fail to
   redirect after submission. Both `AMP-Access-Control-Allow-Source-Origin` and `
   AMP-Redirect-To` response headers had a trailing space appended to their values,
   causing header parsing failures in the AMP runtime.
 * Fixed: “Privacy Settings” re-open button label in the GDPR post-consent UI was
   a hardcoded English string. It is now wrapped with `__()` and translatable.

#### 1.7.3 – 2026-04-30

 * Fixed: Yoast SEO integration now works correctly on all modern Yoast SEO versions(
   v14 and above). The previous guard checked for WPSEO_OpenGraph, a class removed
   in Yoast v14 (2020), causing meta description, Open Graph, and Twitter Card tags
   to be silently omitted from every AMP page on any current Yoast install. The 
   guard now detects both modern (YoastSEO()) and legacy (WPSEO_OpenGraph) APIs.
 * Fixed: Meta description, Open Graph, and Twitter Card tags are now output on 
   AMP pages for Yoast SEO v14+ using the wpseo_head presenter pipeline, replacing
   the deprecated WPSEO_Frontend, WPSEO_Twitter, and wpseo_opengraph APIs which 
   were removed in Yoast v14.
 * Fixed: AMP pages no longer output a duplicate title or robots meta tag when Yoast
   SEO is active. The new presenter filter strips Title, Robots, Canonical, Rel-
   Prev, and Rel-Next presenters since AMP WP manages those independently.
 * Fixed: Homepage title sync with Yoast SEO now works on AMP front pages with Yoast
   v14+ using YoastSEO()->meta->for_post(). Previously the function fell through
   silently on modern Yoast because the WPSEO_Frontend::get_instance() guard evaluated
   to false.
 * Fixed: AMP front page no longer times out when Yoast SEO is active. The new homepage
   title code called Yoast’s meta API, which internally triggers wp_get_document_title()
   and re-fires the pre_get_document_title filter, causing the callback to re-enter
   itself indefinitely. This produced a 300-second PHP timeout visible only on the
   AMP front page. A re-entrancy guard now prevents the loop.
 * Fixed: All In One SEO Pack (AIOSEO) integration now works with AIOSEO v4 and 
   above. The previous code called All_in_One_SEO_Pack() directly, a class removed
   in AIOSEO v4 (2021), so meta description, Open Graph, and Twitter Card tags were
   silently missing from AMP pages on all modern AIOSEO installs. The guard now 
   detects AIOSEO v4+ via the aioseo() function and calls aioseo()->head->output()
   to render the full meta block, while retaining the legacy v3 code path as a fallback.
 * Fixed: AIOSEO homepage title sync now works on v4+ using aioseo()->meta->title-
   >getPostTitle(). The previous call used a non-existent get() method and silently
   returned no title on all modern AIOSEO versions.
 * Fixed: WP-Optimize compatibility fully rewritten. The previous fix attempted 
   to remove a WP-Optimize hook at plugin-load time, but AMP WP loads alphabetically
   before WP-Optimize so the class did not exist yet and the removal never executed.
   Three specific issues are now resolved: (1) HTML compression: WP-Optimize’s output
   buffer ob_start has no AMP check and was compressing AMP HTML; it is now removed
   before it fires. (2) Delay JS: the Delay JS feature uses a regex that matches
   all script tags including AMP runtime and component scripts, rewriting src to
   data-src and preventing them from loading; it is now disabled on AMP pages. (
   3) Page caching: AMP responses are now excluded from WP-Optimize’s page cache
   via the wpo_can_cache_page filter so corrupted output is never stored. CSS and
   JS minification were already safe via WP-Optimize’s own is_amp_endpoint() check.
 * Fixed: WP Fastest Cache compatibility extended to cover all features that have
   no built-in AMP check. Previously only JS combine/minify, CSS combine, lazy load,
   and Google Fonts were disabled on AMP pages. HTML minification (standard and 
   aggressive), CSS minification, inline CSS minification, and HTML comment removal
   are now also disabled; all five ran unconditionally on AMP pages in every prior
   version.
 * Fixed: OneSignal Web Push Notifications integration corrected on four fronts.(
   1) The amp-web-push component was never injected into AMP pages because the add_action
   call was wrapped in an inverted function_exists guard that always evaluated false
   after the function was defined directly above it. (2) The HTTP site toggle was
   saved under the key onesignal_http_site_switch but read back as onesignal_switch_http_site,
   so HTTP mode was never activated. (3) HTTPS helper and permission dialog HTML
   pointed to outdated bundled copies inside the AMP WP plugin instead of the installed
   OneSignal plugin’s own sdk_files, which load the current SDK from cdn.onesignal.
   com. (4) A missing isset on onesignal_app_id generated a PHP notice when the 
   App ID field was left empty.
 * Fixed: Structured data schema type (`schema_type_for_post`) is now validated 
   against the allowed set (`Article`, `NewsArticle`, `BlogPosting`) before being
   passed to the JSON-LD generator. A tampered or corrupted database value could
   previously write an arbitrary `@type` string into the JSON-LD output, producing
   invalid structured data that fails Google’s Rich Results validator.
 * Fixed: `datePublished` and `dateModified` in JSON-LD structured data now use 
   ISO 8601 datetime format with timezone offset (`DATE_ATOM`, e.g. `2024-01-15T10:
   30:00+05:00`) instead of date-only format (`Y-m-d`). The previous date-only format
   omits time and timezone information, which is non-compliant with the Schema.org`
   DateTime` specification and reduces precision for Google’s structured data parser.
 * Fixed: `interactionStatistic.userInteractionCount` in JSON-LD structured data
   is now cast to integer before output. `get_comments_number()` returns a string;
   Schema.org defines `userInteractionCount` as a `Number` type, so a string value
   caused Google’s Rich Results validator to report a type mismatch on every post.
 * Fixed: `Article`, `NewsArticle`, and `BlogPosting` schemas now always include
   an `image` field. When a post has no featured image, the generator falls back
   to the organization logo (when a logo is configured in AMP WP branding settings).
   Google treats `image` as required for all Article-type rich results: posts without
   a featured image previously emitted no `image` at all, silently disqualifying
   them from rich result eligibility in Google Search.
 * Fixed: Yoast SEO homepage JSON-LD sync now actually fires on AMP pages. The `
   amp_wp_json_ld_website_` filter (note the trailing underscore, which is the real
   filter name emitted by the generator) was registered without the trailing underscore
   as `amp_wp_json_ld_website`, causing the callback to be permanently silently 
   skipped. The site name and alternate name set in Yoast SEO options were never
   merged into the WebSite schema on AMP homepages.
 * Removed: Multi Rating compatibility. The plugin was closed on WordPress.org and
   has not been updated since 2018; it is no longer installable. The compatibility
   block was also registered unconditionally with no detection guard, meaning three
   dead function calls fired on every AMP page load even when Multi Rating was not
   installed. Removed the `add_action` call, the `multi_rating()` method, and the
   file-header reference.
 * Verified: Snip Rich Snippets (`rich-snippets-schema`) compatibility with AMP 
   pages confirmed correct and complete. AMP WP’s template system does not fire `
   wp_head`, so Snip’s own head hook is silent on AMP pages. The compatibility layer
   re-routes Snip’s `print_snippets` output to `amp_wp_template_head` or `amp_wp_template_footer`(
   respecting Snip’s own “snippets in footer” setting) exactly once per request.
   Snip’s JSON-LD output is AMP-spec-valid (`<script type="application/ld+json">`
   is permitted in AMP pages) and coexists with AMP WP’s own structured data blocks
   without duplication.
 * Fixed: wpForo Forum compatibility now works correctly with wpForo 3.x. The previous
   detection used `class_exists('wpForo')`, which always returned false on wpForo
   3.x because that version moved to a PHP namespace (`wpforo\wpforo`). As a result,
   the `amp_wp_amp_version_exists` filter was never registered, and AMP WP silently
   served AMP pages on wpForo forum URLs on all modern wpForo installs. Detection
   now uses `defined('WPFORO_VERSION')`, which is reliably set by all wpForo versions.

#### 1.7.2 – 2026-04-26

 * Fixed: Google Analytics AMP tag now correctly detects GA4 (`G-XXXXXXXX`) vs Universal
   Analytics (`UA-XXXXXXX-X`) IDs. GA4 IDs now output `<amp-analytics type="gtag"
   >` with `gtag_id` / `config` vars, while UA IDs continue to use the legacy `type
   ="googleanalytics"` vendor. This resolves the persistent `[AmpAnalytics googleanalytics]
   Warning: [object Object]` console error that appeared after migrating to a GA4
   Measurement ID.
 * Fixed: JSON-LD structured data: 11 Schema.org / Google Rich Results compliance
   issues resolved: `mainEntityOfPage` is now a typed `WebPage` object instead of
   a plain URL; `publisher` outputs an inline `Organization` when no logo is configured
   so the `#organization` reference never dangles; `headline` capped at 110 characters
   per Google AMP article spec; all `@context` values normalised to `https://schema.
   org` (no trailing slash); all `@id` values upgraded to absolute URLs; `WebSite`
   schema uses `description` instead of `alternateName` for the site tagline; `AudioObject`
   now includes the required `name` property; `post_excerpt` is sanitised before
   output; `wordCount` restricted to Article sub-types only; `WebPage potentialAction`
   corrected to a direct `SearchAction` object; `JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE`
   added to JSON output flags.
 * Fixed: AdSense Auto Ads (and any custom `<head>` code) now outputs via the `amp_wp_template_head_deferred`
   hook at priority 5 instead of `amp_wp_template_head`, ensuring the snippet is
   injected after AMP boilerplate styles are written, which is required for `<amp-
   auto-ads>` to be recognised and fired correctly by the AMP runtime.
 * Improved: Upgraded Font Awesome from 4.7.0 (MaxCDN) to 6.7.2 (cdnjs), eliminating
   browser console warnings about incorrect glyph bounding boxes present in the 
   FA 4.7.0 font file. The v4-shims stylesheet is loaded automatically so all existing`
   fa fa-*` icon classes continue to work with no template changes required.
 * Improved: WordPress Coding Standards (PHPCS) compliance in `amp-wp-template-functions.
   php`: all output values are now properly escaped (`esc_attr()`, `wp_kses_post()`),
   loose `==` comparisons replaced with strict `===`, variable assignments moved
   out of conditions, `in_array()` calls updated with strict mode, reserved-keyword
   parameter names renamed, and PHPDoc parameter annotations corrected throughout.
 * Improved: WordPress Coding Standards (PHPCS) compliance in `class-amp-wp-html-
   util.php`: added file-level docblock, renamed camelCase local variables to snake_case
   in `renameElement()`, fixed variable assignments in conditions in `get_child_tag_attribute()`,
   corrected a `@param` name mismatch in the `child()` method docblock, and added`
   phpcs:ignore` annotations for PHP DOM API built-in properties (`parentNode`, `
   childNodes`, `ownerDocument`, etc.) that cannot be renamed.

#### 1.7.1 – 2026-04-26

 * Fixed: Select2 CSS in the admin now scoped to `.select2-container.amp-wp-select-
   container`, preventing style conflicts when ACF (Advanced Custom Fields) or other
   plugins ship their own Select2 instance on the same admin page.
 * Fixed: Comments section on single posts no longer hides the “Add Comment” button
   when a post has zero comments; comments are open so visitors can start a discussion.
   The comment list itself is still only rendered when comments exist.
 * Improved: Add-ons tab card layout: Install/Update action button now appears above
   the version info line, and the action area uses flexbox for consistent alignment
   across varying content lengths.
 * Fixed: PHP Warning “Undefined array key amp_wp_settings_nonce_field” in settings
   save handler. The `||` operator caused the nonce value to be read before its 
   existence was confirmed; corrected to `&&`.
 * Fixed: WP Rocket redirect loop on URLs excluded from AMP. WP Rocket was serving
   a stale cached redirect (non-AMP -> AMP) after the URL was added to the exclusion
   list, while the plugin redirected back (AMP -> non-AMP). Excluded URLs are now
   pushed into WP Rocket’s `rocket_cache_exclude_uris` bypass list so cached redirects
   are never served for them, and `DONOTCACHEPAGE` is set on the current request
   to prevent a new cache file from being written.
 * Improved: `class-amp-wp-plugin-compatibility.php` file and class docblocks rewritten
   to professional WordPress PHPDoc standard. The file header now documents all 
   supported third-party plugins grouped by category (Cache & Performance, SEO, 
   Multilingual, Media & Lazy Load, Social & Comments, Forms, Structured Data, Links&
   Permalinks, Miscellaneous) with plugin URLs; class docblock describes the conditional-
   detection architecture.
 * Removed: WP Speed Grades Lite compatibility. The plugin was closed on WordPress.
   org on 1 March 2021 for guideline violation and is no longer available for download.
   Removed the `WP_SPEED_GRADES_VERSION` detection block, the `pre_init()` method,
   and all references in docblocks.
 * Fixed: Translated AMP pages returning 404 when Polylang is active with subdirectory
   language URLs (e.g. `/uk/category/post/amp/`). The AMP URL transformer was reading
   the language prefix segment (e.g. `uk`) as a post slug and failing to detect 
   the AMP endpoint. Language slugs are now added to the URL transformer exclusion
   list when Polylang is configured in subdirectory mode, mirroring the existing
   WPML fix.

#### 1.7.0 – 2026-04-23

 * Added: Add-ons tab now shows installed and latest version for each premium add-
   on (e.g. “Installed: v2.0.0 | Latest: v2.0.0”).
 * Added: Download button on the Add-ons tab hides when the add-on is already installed
   and up to date.
 * Added: Update button appears on the Add-ons card when an installed add-on is 
   outdated (installed version < latest version).
 * Added: Latest version is fetched from the public `amp-wp-addon-versions` GitHub
   repository and cached for 12 hours via WordPress transients.
 * Added: Manual version cache refresh: visiting the Add-ons page with `?amp_refresh_versions
   =1` clears the cached version and forces a fresh fetch.
 * Added: Full Help & Documentation page: replaces the placeholder with Getting 
   Started, Content Control, Design, Analytics & Ads, Embeds, Add-Ons, and FAQ sections.
 * Fixed: Undefined variable `$page` warning in `amp-wp-admin-header.php`. The active
   tab highlight now reads the current page from the URL query parameter directly.
 * Fixed: `wp_redirect()` replaced with `wp_safe_redirect()` + `exit` on activation
   redirect to prevent open redirect and ensure execution stops.
 * Fixed: `amp_wp_version_check_using_wpapi()` wrapped in `function_exists` guard
   and moved to utility functions to prevent fatal errors on duplicate inclusion.

#### 1.6.0 – 2026-04-14

 * Added: Instagram Reels (`/reel/`) and IGTV (`/tv/`) embed support alongside existing`/
   p/` posts via `amp-instagram`.
 * Added: `data-captioned` passthrough: preserves Instagram caption flag when the
   original embed included `data-instgrm-captioned`.
 * Added: Auto layout detection for `amp-iframe`: sets `layout="responsive"` when
   both width and height are present; `layout="fixed-height"` when only height is
   available.
 * Added: Pass-through of `layout`, `resizable`, `scrolling`, and `srcdoc` attributes
   to `amp-iframe` for fuller AMP spec coverage.
 * Improved: `amp-facebook` output now includes a proper closing tag and corrected
   attribute spacing.
 * Improved: `amp-playbuzz` component now supports both `src` (full URL) and `data-
   item` (item ID) conventions, plus optional `data-item-info`, `data-share-buttons`,
   and `data-comments` attributes.
 * Improved: `amp-instagram` dimensions updated to `1x1` with `layout="responsive"`
   per AMP documentation.
 * Improved: JSON-LD `@context` updated from `http://schema.org` to `https://schema.
   org`.
 * Improved: `SearchAction` structured data updated to use the `EntryPoint` object
   format with `urlTemplate` and `search_term_string` per current Schema.org specification.
 * Improved: Tumblr share button updated to the current widget API endpoint (`https://
   www.tumblr.com/widgets/share/tool`) with correct parameters.
 * Improved: `aria-label` attribute on social share buttons corrected (was producing
   malformed HTML).
 * Fixed: PHP 8 compatibility, replaced `@fopen()` error suppression in `Fastimage.
   php` with a proper `set_error_handler` / `restore_error_handler` pattern.
 * Fixed: PHP 8 compatibility, replaced `@getimagesize()` suppression with an explicit`
   false !== $size` check.
 * Fixed: Replaced all deprecated `join()` calls with `implode()` across the codebase.
 * Removed: `amp-addthis` from the supported AMP components list (component retired
   by the AMP Project).
 * Removed: `amp-gfycat` from the supported AMP components …

## Meta

 *  Version **1.7.6**
 *  Last updated **11 hours ago**
 *  Active installations **700+**
 *  WordPress version ** 5.0 or higher **
 *  Tested up to **6.9.4**
 *  PHP version ** 7.4 or higher **
 * Tags
 * [accelerated mobile pages](https://wordpress.org/plugins/tags/accelerated-mobile-pages/)
   [amp](https://wordpress.org/plugins/tags/amp/)[google amp](https://wordpress.org/plugins/tags/google-amp/)
   [mobile](https://wordpress.org/plugins/tags/mobile/)[Page Speed](https://wordpress.org/plugins/tags/page-speed/)
 *  [Advanced View](https://wordpress.org/plugins/amp-wp/advanced/)

## Ratings

 4.5 out of 5 stars.

 *  [  45 5-star reviews     ](https://wordpress.org/support/plugin/amp-wp/reviews/?filter=5)
 *  [  3 4-star reviews     ](https://wordpress.org/support/plugin/amp-wp/reviews/?filter=4)
 *  [  1 3-star review     ](https://wordpress.org/support/plugin/amp-wp/reviews/?filter=3)
 *  [  1 2-star review     ](https://wordpress.org/support/plugin/amp-wp/reviews/?filter=2)
 *  [  5 1-star reviews     ](https://wordpress.org/support/plugin/amp-wp/reviews/?filter=1)

[Your review](https://wordpress.org/support/plugin/amp-wp/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/amp-wp/reviews/)

## Contributors

 *   [ Pixelative ](https://profiles.wordpress.org/pixelative/)
 *   [ Mohsin Rafique ](https://profiles.wordpress.org/mohsinrafique/)

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/amp-wp/)

## Donate

Would you like to support the advancement of this plugin?

 [ Donate to this plugin ](https://wise.com/pay/me/mohsinr301)