{"id":90521,"date":"2018-09-17T11:45:21","date_gmt":"2018-09-17T11:45:21","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/amp-wp\/"},"modified":"2026-05-14T17:01:43","modified_gmt":"2026-05-14T17:01:43","slug":"amp-wp","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/amp-wp\/","author":16258819,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.7.8","stable_tag":"1.7.8","tested":"6.9.4","requires":"5.0","requires_php":"7.4","requires_plugins":null,"header_name":"AMP WP","header_author":"Mohsin Rafique, Pixelative","header_description":"Supporting everything in WordPress, it's the best Google AMP solution to date.","assets_banners_color":"f8d6d5","last_updated":"2026-05-14 17:01:43","external_support_url":"","external_repository_url":"","donate_link":"https:\/\/wise.com\/pay\/me\/mohsinr301","header_plugin_uri":"https:\/\/wordpress.org\/plugins\/amp-wp","header_author_uri":"https:\/\/mohsinrafique.com","rating":4.4,"author_block_rating":0,"active_installs":700,"downloads":80231,"num_ratings":56,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","faq","changelog"],"tags":{"1.0.0":{"tag":"1.0.0","author":"pixelative","date":"2018-09-20 17:34:40"},"1.0.1":{"tag":"1.0.1","author":"pixelative","date":"2018-09-20 17:34:40"},"1.0.2":{"tag":"1.0.2","author":"pixelative","date":"2018-09-20 17:34:40"},"1.0.3":{"tag":"1.0.3","author":"pixelative","date":"2018-09-25 20:20:34"},"1.0.4":{"tag":"1.0.4","author":"pixelative","date":"2018-10-30 19:28:42"},"1.0.5":{"tag":"1.0.5","author":"pixelative","date":"2018-10-31 08:08:12"},"1.1.0":{"tag":"1.1.0","author":"pixelative","date":"2018-11-10 06:00:35"},"1.1.1":{"tag":"1.1.1","author":"pixelative","date":"2018-11-16 23:18:59"},"1.2.0":{"tag":"1.2.0","author":"pixelative","date":"2018-11-29 14:34:08"},"1.2.1":{"tag":"1.2.1","author":"pixelative","date":"2018-12-02 07:19:14"},"1.2.2":{"tag":"1.2.2","author":"pixelative","date":"2018-12-02 08:18:33"},"1.3.0":{"tag":"1.3.0","author":"pixelative","date":"2018-12-03 12:38:22"},"1.3.1":{"tag":"1.3.1","author":"pixelative","date":"2018-12-03 17:03:40"},"1.4.0":{"tag":"1.4.0","author":"pixelative","date":"2018-12-12 18:27:57"},"1.4.1":{"tag":"1.4.1","author":"pixelative","date":"2019-01-04 20:11:03"},"1.4.2":{"tag":"1.4.2","author":"pixelative","date":"2019-01-17 21:06:44"},"1.4.3":{"tag":"1.4.3","author":"pixelative","date":"2019-01-26 00:51:44"},"1.4.3.1":{"tag":"1.4.3.1","author":"pixelative","date":"2019-02-11 20:01:48"},"1.5.0":{"tag":"1.5.0","author":"pixelative","date":"2019-03-26 16:02:17"},"1.5.1":{"tag":"1.5.1","author":"pixelative","date":"2019-03-26 18:38:46"},"1.5.10":{"tag":"1.5.10","author":"pixelative","date":"2019-09-17 18:54:20"},"1.5.11":{"tag":"1.5.11","author":"pixelative","date":"2019-11-25 16:51:04"},"1.5.12":{"tag":"1.5.12","author":"pixelative","date":"2021-06-23 17:52:05"},"1.5.13":{"tag":"1.5.13","author":"pixelative","date":"2021-08-19 17:16:27"},"1.5.14":{"tag":"1.5.14","author":"pixelative","date":"2021-12-24 15:38:16"},"1.5.15":{"tag":"1.5.15","author":"mohsinrafique","date":"2023-07-09 21:36:03"},"1.5.16":{"tag":"1.5.16","author":"pixelative","date":"2024-05-02 21:34:49"},"1.5.17":{"tag":"1.5.17","author":"mohsinrafique","date":"2026-01-28 08:09:23"},"1.5.18":{"tag":"1.5.18","author":"mohsinrafique","date":"2026-01-28 08:09:23"},"1.5.19":{"tag":"1.5.19","author":"mohsinrafique","date":"2026-04-02 23:05:20"},"1.5.2":{"tag":"1.5.2","author":"pixelative","date":"2019-03-27 05:54:45"},"1.5.3":{"tag":"1.5.3","author":"pixelative","date":"2019-04-03 09:04:12"},"1.5.4":{"tag":"1.5.4","author":"pixelative","date":"2019-04-03 09:04:12"},"1.5.5":{"tag":"1.5.5","author":"pixelative","date":"2019-04-18 17:35:41"},"1.5.6":{"tag":"1.5.6","author":"pixelative","date":"2019-04-29 19:30:35"},"1.5.7":{"tag":"1.5.7","author":"pixelative","date":"2019-04-29 19:30:35"},"1.5.8":{"tag":"1.5.8","author":"pixelative","date":"2019-07-18 10:08:06"},"1.5.9":{"tag":"1.5.9","author":"pixelative","date":"2019-09-16 19:09:53"},"1.6.0":{"tag":"1.6.0","author":"mohsinrafique","date":"2026-04-14 21:11:15"},"1.7.0":{"tag":"1.7.0","author":"mohsinrafique","date":"2026-04-23 18:44:19"},"1.7.1":{"tag":"1.7.1","author":"mohsinrafique","date":"2026-04-25 19:54:14"},"1.7.2":{"tag":"1.7.2","author":"mohsinrafique","date":"2026-04-26 00:20:26"},"1.7.3":{"tag":"1.7.3","author":"mohsinrafique","date":"2026-04-30 11:10:18"},"1.7.4":{"tag":"1.7.4","author":"mohsinrafique","date":"2026-04-30 20:42:52"},"1.7.5":{"tag":"1.7.5","author":"mohsinrafique","date":"2026-05-07 09:20:05"},"1.7.6":{"tag":"1.7.6","author":"mohsinrafique","date":"2026-05-11 22:22:08"},"1.7.7":{"tag":"1.7.7","author":"mohsinrafique","date":"2026-05-14 14:37:30"},"1.7.8":{"tag":"1.7.8","author":"mohsinrafique","date":"2026-05-14 17:01:43"}},"upgrade_notice":{"1.7.8":"<p><strong>AdSense Auto Ads for AMP is now turnkey end-to-end.<\/strong> AMP WP 1.7.7 added the <strong>Enable Google Auto Ads<\/strong> toggle (loader in <code>); this release completes the picture by auto-emitting the matching<\/code> element right after `` on every AMP page. Closes the AMP validator error &quot;The extension &#039;amp-auto-ads&#039; was found on this page, but is unused. Please remove this extension.&quot; that surfaced on sites running Google Site Kit, because Site Kit&#039;s AdSense AMP integration only fires for the official Automattic AMP plugin and never injected the body element on AMP WP routes. <strong>Setup:<\/strong> (1) <strong>AMP WP -&gt; Settings -&gt; General<\/strong>, tick <strong>Enable Google Auto Ads<\/strong>, save. (2) Publisher ID is auto-resolved from Google Site Kit&#039;s AdSense module when Site Kit is installed and connected - nothing else to do. (3) Without Site Kit, supply your ID via the new <code>amp_wp_adsense_publisher_id<\/code> filter from your theme&#039;s <code>functions.php<\/code> or a mu-plugin. The filter accepts <code>ca-pub-XXXX<\/code>, <code>pub-XXXX<\/code>, or the bare numeric ID and AMP WP normalises before output; emission is silently skipped when no ID is resolvable so the page stays validator-clean. New public API: function <code>amp_wp_get_adsense_publisher_id()<\/code>, function <code>amp_wp_render_auto_ads_element()<\/code>, filter <code>amp_wp_adsense_publisher_id<\/code>.<\/p>","1.7.7":"<p>Recommended for all users. Critical fix for sites using the <strong>GDPR Compliance<\/strong> banner: the EU country list inside `` was being emitted as a corrupted HTML-encoded string (via <code>esc_js()<\/code> instead of <code>wp_json_encode()<\/code>), causing the AMP runtime to reject the whole config with a &quot;country ... not valid, will be ignored&quot; console error and silently disabling the geo-gated consent banner on every page. Update immediately if you rely on the GDPR consent banner. Also adds a new <strong>native Google Auto Ads toggle<\/strong> on the <strong>Settings &gt; General<\/strong> page - enabling it enqueues the <code>amp-auto-ads<\/code> runtime loader via the canonical AMP component pipeline so admins no longer need to paste the script tag into the Customizer&#039;s head-code field; the manual loader is auto-cleaned on save. Plus a full WPCS sweep of the Tez theme directory (37 files, 49 errors and 31 warnings down to 0\/0, no behaviour change), and a tidy-up that removes a dormant placement-manager file from core.<\/p>","1.7.6":"<p>Recommended for all users. Three SEO-impacting fixes: (1) <code>\/favicon.ico<\/code> and any other root-level static-file request on mobile no longer 302s to <code>\/\/amp<\/code> and 404s. (2) Search-engine crawlers (Googlebot-Mobile, Bingbot, social-card scrapers) are no longer caught by the mobile auto-redirect to AMP, fixing &quot;Redirect error&quot; rows in Google Search Console Page Indexing. After updating, click &quot;Validate fix&quot; on the affected URLs in GSC and Google will re-crawl within 1-7 days. (3) Pagination on AMP archives now works for every URL shape (<code>\/shop\/amp\/page\/N\/<\/code>, <code>\/product-category\/\/amp\/page\/N\/<\/code>, <code>\/category\/\/amp\/page\/N\/<\/code>, etc.) - previously broken when the AMP token appeared in the middle of the URI. Also introduces the new &quot;Premium Extensions&quot; tab (hidden until at least one AMP WP family add-on is active) and the new public APIs <code>amp_wp_register_premium_extension()<\/code> and <code>amp_wp_register_template_path()<\/code> that let AMP WP family add-ons (CF7, Comments, WooCommerce, WPForms, Gravity Forms, Ads Manager) self-register and ship their own AMP templates.<\/p>","1.7.5":"<p>Recommended for all users. Critical fix: mobile visitors could get stuck in a &quot;too many redirects&quot; loop on AMP URLs after admins changed the AMP-exclusion settings. Plugin-issued redirects now use <code>302 Found<\/code> + <code>nocache_headers()<\/code>, with a one-shot <code>Clear-Site-Data: &amp;quot;cache&amp;quot;<\/code> on AMP-excluded redirects to auto-recover any client that already has a stale <code>301<\/code> pinned in its browser cache. The desktop-side cache-plugin fallback is now uncacheable as well, so caching plugins cannot serve a desktop response with a UA-sniffing redirect script to a mobile visitor. Also recommended for users of the AMP WP Comments add-on: Reply links were not appearing on threaded AMP comment lists in WordPress 6.8, the Reply button showed the wrong label, and <code>amp-state<\/code> blocks were silently stripped. Also fixes a malformed AFS Analytics JSON that disabled analytics on AMP pages when AFS Analytics was configured.<\/p>","1.7.4":"<p>Recommended for all users. The header and sidebar logo was silently stripped on every AMP page since v1.7.2 due to a PHPCS escaping regression. Update immediately if your logo is not appearing.<\/p>","1.7.3":"<p>Recommended for all users running any of these plugins alongside AMP WP:\n* Yoast SEO: meta description, Open Graph, and Twitter Card tags were silently missing on all AMP pages with Yoast v14 and above. Duplicate title and robots tags also fixed. A 300-second timeout on the AMP front page caused by an infinite callback loop is also resolved.\n* All In One SEO Pack: meta description, Open Graph, and Twitter Card tags were silently missing on all AMP pages with AIOSEO v4 and above. Homepage title sync also fixed.\n* WP-Optimize: HTML compression, Delay JS, and page caching all previously ran unchecked on AMP pages and could break or cache corrupted output. All three are now correctly disabled for AMP responses.\n* WP Fastest Cache: HTML minification, CSS minification, and comment removal all ran unconditionally on AMP pages. All are now correctly disabled.\n* OneSignal Web Push Notifications: the subscribe\/unsubscribe widget was never rendered on AMP pages due to a code bug. Now fixed.\n* wpForo Forum: AMP pages were incorrectly served on wpForo forum URLs on all wpForo 3.x installs. The detection bug is now fixed.<\/p>","1.7.2":"<p>Recommended for all users. Key fixes in this release:\n* AdSense Auto Ads: corrected head injection order so Auto Ads fire correctly on all AMP pages.\n* Font Awesome: upgraded from 4.7.0 to 6.7.2, eliminating browser console font warnings. No changes to your icons or templates required.\n* Google Analytics: GA4 Measurement IDs (G-XXXXXXXX) now use the correct AMP analytics tag. Fixes the console warning seen after migrating from Universal Analytics.\n* Structured Data: 11 JSON-LD \/ Schema.org issues resolved for better Google Rich Results compliance.<\/p>","1.7.1":"<p>Recommended if you use ACF or other plugins that ship Select2, fixes admin CSS conflicts. Also fixes a UX bug where the &quot;Add Comment&quot; button was hidden on posts with zero comments.<\/p>","1.6.0":"<p>Recommended for all users. Adds Instagram Reels and IGTV support, improves AMP iframe handling and layout detection, fixes PHP 8 compatibility issues, updates JSON-LD structured data to current Schema.org standards, and removes two retired AMP components.<\/p>","1.5.19":"<p>Recommended for PHP 8.4 users. Resolves a deprecated return-type warning in the HTML utility class.<\/p>","1.5.10":"<p>Important fix for sites using the &quot;AMP URL at end&quot; format, which resolves a self-canonical AMP URL issue.<\/p>"},"ratings":{"1":6,"2":1,"3":1,"4":3,"5":45},"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":2552940,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":2552940,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":1946984,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":1946984,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.0","1.0.1","1.0.2","1.0.3","1.0.4","1.0.5","1.1.0","1.1.1","1.2.0","1.2.1","1.2.2","1.3.0","1.3.1","1.4.0","1.4.1","1.4.2","1.4.3","1.4.3.1","1.5.0","1.5.1","1.5.10","1.5.11","1.5.12","1.5.13","1.5.14","1.5.15","1.5.16","1.5.17","1.5.18","1.5.19","1.5.2","1.5.3","1.5.4","1.5.5","1.5.6","1.5.7","1.5.8","1.5.9","1.6.0","1.7.0","1.7.1","1.7.2","1.7.3","1.7.4","1.7.5","1.7.6","1.7.7","1.7.8"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":1946984,"resolution":"1","location":"assets","locale":"","width":609,"height":550},"screenshot-10.png":{"filename":"screenshot-10.png","revision":1946984,"resolution":"10","location":"assets","locale":"","width":609,"height":550},"screenshot-11.png":{"filename":"screenshot-11.png","revision":1946984,"resolution":"11","location":"assets","locale":"","width":609,"height":550},"screenshot-12.png":{"filename":"screenshot-12.png","revision":1946984,"resolution":"12","location":"assets","locale":"","width":609,"height":550},"screenshot-13.png":{"filename":"screenshot-13.png","revision":1984423,"resolution":"13","location":"assets","locale":"","width":609,"height":550},"screenshot-14.png":{"filename":"screenshot-14.png","revision":1993056,"resolution":"14","location":"assets","locale":"","width":609,"height":550},"screenshot-2.png":{"filename":"screenshot-2.png","revision":1946984,"resolution":"2","location":"assets","locale":"","width":609,"height":550},"screenshot-3.png":{"filename":"screenshot-3.png","revision":1946984,"resolution":"3","location":"assets","locale":"","width":609,"height":550},"screenshot-4.png":{"filename":"screenshot-4.png","revision":1946984,"resolution":"4","location":"assets","locale":"","width":609,"height":550},"screenshot-5.png":{"filename":"screenshot-5.png","revision":1946984,"resolution":"5","location":"assets","locale":"","width":609,"height":550},"screenshot-6.png":{"filename":"screenshot-6.png","revision":1993056,"resolution":"6","location":"assets","locale":"","width":609,"height":550},"screenshot-7.png":{"filename":"screenshot-7.png","revision":1946984,"resolution":"7","location":"assets","locale":"","width":609,"height":550},"screenshot-8.png":{"filename":"screenshot-8.png","revision":1946984,"resolution":"8","location":"assets","locale":"","width":609,"height":550},"screenshot-9.png":{"filename":"screenshot-9.png","revision":1946984,"resolution":"9","location":"assets","locale":"","width":609,"height":550}},"screenshots":{"1":"Home Page","2":"Single Post Page","3":"Tags, Social Icons, Related Posts, Comments, and Footer","4":"Search &amp; Archive Page","5":"100% Valid AMP Content","6":"AMP WP Options Panel","7":"AMP Auto Ads Support","8":"Compatible with Major Cache Plugins","9":"Embed Images, Videos, Audios &amp; iFrames","10":"Toggle Search &amp; Header","11":"Recent Comments","12":"Sidebar, Social Icons &amp; Related Posts","13":"Core WordPress Customizer Integration","14":"AMP WP Settings Panel"},"jetpack_post_was_ever_published":false},"plugin_section":[],"plugin_tags":[1881,1882,1884,841,5896],"plugin_category":[],"plugin_contributors":[148927,161913],"plugin_business_model":[],"class_list":["post-90521","plugin","type-plugin","status-publish","hentry","plugin_tags-accelerated-mobile-pages","plugin_tags-amp","plugin_tags-google-amp","plugin_tags-mobile","plugin_tags-page-speed","plugin_contributors-mohsinrafique","plugin_contributors-pixelative","plugin_committers-mohsinrafique","plugin_committers-pixelative","plugin_support_reps-pixelative"],"banners":{"banner":"https:\/\/ps.w.org\/amp-wp\/assets\/banner-772x250.png?rev=1946984","banner_2x":"https:\/\/ps.w.org\/amp-wp\/assets\/banner-1544x500.png?rev=1946984","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/amp-wp\/assets\/icon-128x128.png?rev=2552940","icon_2x":"https:\/\/ps.w.org\/amp-wp\/assets\/icon-256x256.png?rev=2552940","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/amp-wp\/assets\/screenshot-1.png?rev=1946984","caption":"Home Page"},{"src":"https:\/\/ps.w.org\/amp-wp\/assets\/screenshot-2.png?rev=1946984","caption":"Single Post Page"},{"src":"https:\/\/ps.w.org\/amp-wp\/assets\/screenshot-3.png?rev=1946984","caption":"Tags, Social Icons, Related Posts, Comments, and Footer"},{"src":"https:\/\/ps.w.org\/amp-wp\/assets\/screenshot-4.png?rev=1946984","caption":"Search &amp; Archive Page"},{"src":"https:\/\/ps.w.org\/amp-wp\/assets\/screenshot-5.png?rev=1946984","caption":"100% Valid AMP Content"},{"src":"https:\/\/ps.w.org\/amp-wp\/assets\/screenshot-6.png?rev=1993056","caption":"AMP WP Options Panel"},{"src":"https:\/\/ps.w.org\/amp-wp\/assets\/screenshot-7.png?rev=1946984","caption":"AMP Auto Ads Support"},{"src":"https:\/\/ps.w.org\/amp-wp\/assets\/screenshot-8.png?rev=1946984","caption":"Compatible with Major Cache Plugins"},{"src":"https:\/\/ps.w.org\/amp-wp\/assets\/screenshot-9.png?rev=1946984","caption":"Embed Images, Videos, Audios &amp; iFrames"},{"src":"https:\/\/ps.w.org\/amp-wp\/assets\/screenshot-10.png?rev=1946984","caption":"Toggle Search &amp; Header"},{"src":"https:\/\/ps.w.org\/amp-wp\/assets\/screenshot-11.png?rev=1946984","caption":"Recent Comments"},{"src":"https:\/\/ps.w.org\/amp-wp\/assets\/screenshot-12.png?rev=1946984","caption":"Sidebar, Social Icons &amp; Related Posts"},{"src":"https:\/\/ps.w.org\/amp-wp\/assets\/screenshot-13.png?rev=1984423","caption":"Core WordPress Customizer Integration"},{"src":"https:\/\/ps.w.org\/amp-wp\/assets\/screenshot-14.png?rev=1993056","caption":"AMP WP Settings Panel"}],"raw_content":"<!--section=description-->\n<p><strong>AMP WP<\/strong> is the most feature-rich, developer-friendly, and beginner-ready Google AMP plugin available for WordPress, completely free.<\/p>\n\n<p>Originally built by <strong><a href=\"https:\/\/pixelative.co\">Pixelative<\/a><\/strong>, a professional web development agency, AMP WP is now independently developed and maintained by <strong><a href=\"https:\/\/mohsinrafique.com\">Mohsin Rafique<\/a><\/strong>, 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.<\/p>\n\n<p><a href=\"https:\/\/pixelspress.com\/amp\">Online Demo<\/a> | <a href=\"https:\/\/1c8979da.sibforms.com\/serve\/MUIFAPfaW_zG5aVJNBG78I1qIu30utV8kT5_ERiosqVMstRk9Nj1o6RVbEbyaJkvyZ9TQ3b79YDkpPjsyd99NmbxAlNtZQrx9TkcFAF3V6DvgcoiCcnaZkgvPxl_OpctNUzI-G7xDKxwMq2d2Cm2RteW4LoOxEi-XMmdvhfCiMDxfBsOx18Pd9U1xsTcOqIdyT9WccheL83rrsCeeQ==\">CF7 Premium Extension<\/a> | <a href=\"mailto:mohsin.rafique@gmail.com\">Support<\/a><\/p>\n\n\n\n<h3>Why AMP WP?<\/h3>\n\n<p>Google's Accelerated Mobile Pages (AMP) technology delivers pages up to <strong>5x faster<\/strong> 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.<\/p>\n\n\n\n<h3>Free Features<\/h3>\n\n<p><strong>Performance &amp; Compatibility<\/strong>\n* Full Google AMP specification compliance (100% valid AMP output)\n* PHP 8.x compatible (tested through PHP 8.4)\n* Compatible with all major caching plugins (WP Rocket, SG Optimizer, W3 Total Cache, and more)\n* Compatible with Jetpack\n* Compatible with Yoast SEO (100%)\n* Compatible with \"Automattic AMP\" plugin\n* Gutenberg block editor support\n* RTL language support (100%)\n* GDPR compliant<\/p>\n\n<p><strong>Content &amp; Embeds<\/strong>\n* Automatic AMP conversion for Posts, Pages, and Custom Post Types\n* Embed Images, Videos, Audios, and iFrames: YouTube, Vimeo, Twitter, Facebook, SoundCloud, Instagram (Posts, Reels &amp; TV)\n* Lightbox for Images\n* Slider Support\n* Internal AMP Linking\n* Native AMP Search<\/p>\n\n<p><strong>Design &amp; Customization<\/strong>\n* Two listing layouts: Classic View and List View\n* Customizable color scheme\n* Custom CSS options\n* Sticky Header\n* AMP WordPress Navigation Menu\n* Custom AMP Front Page\n* Social Icons<\/p>\n\n<p><strong>Control<\/strong>\n* Show\/Hide AMP for individual Posts, Pages, and Custom Post Types\n* Show\/Hide AMP for Taxonomies (Categories, Tags, Custom)\n* Show\/Hide AMP mobile redirections\n* Show\/Hide AMP on Search pages\n* Show\/Hide Date, Author, and Thumbnail across Archive, Single Post, Related Posts, and Slider\n* Show\/Hide Tags on Single Post pages\n* Enable\/Disable Structured Data (JSON-LD Schema)<\/p>\n\n<p><strong>Engagement &amp; Analytics<\/strong>\n* Related Posts (with thumbnail, date, and author controls)\n* Recent Comments\n* Notice Bar\n* Sidebar\n* Social Sharing Buttons\n* OneSignal Push Notifications integration\n* Third-party analytics support: Google Analytics, Facebook Pixel, Segment, Quantcast, Alexa Metrics, Chartbeat, comScore, Yandex Metrica, AFS Analytics, Adobe Analytics<\/p>\n\n<p><strong>Ads<\/strong>\n* Google AdSense Auto Ads for AMP support<\/p>\n\n<p><strong>Multilingual<\/strong>\n* Translation Panel included\n* Contact us at <code>mohsin.rafique@gmail.com<\/code> to contribute translations<\/p>\n\n\n\n<h3>Maintained by Mohsin Rafique<\/h3>\n\n<p>AMP WP was originally created by <strong><a href=\"https:\/\/pixelative.co\">Pixelative<\/a><\/strong>, 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 <strong>Mohsin Rafique<\/strong>, a seasoned WordPress engineer with deep expertise in AMP specification compliance, PHP performance, and modern web standards.<\/p>\n\n<p>For support, custom AMP theme development, or white-label licensing, contact <strong>Mohsin Rafique<\/strong> at <a href=\"https:\/\/mohsinrafique.com\">mohsinrafique.com<\/a> or <a href=\"mailto:mohsin.rafique@gmail.com\">mohsin.rafique@gmail.com<\/a>.<\/p>\n\n\n\n<h4>Credits<\/h4>\n\n<ul>\n<li><a href=\"https:\/\/wppb.me\/\">WordPress Plugin Boilerplate Generator<\/a> by Tom McFarlin, License: GPLv2<\/li>\n<li><a href=\"http:\/\/necolas.github.io\/normalize.css\/\">normalize.css<\/a>, License: MIT<\/li>\n<li><a href=\"https:\/\/fonts.google.com\/specimen\/Karla\">Karla<\/a> by Jonathan Pinhorn, License: SIL OFL<\/li>\n<li><a href=\"https:\/\/fonts.google.com\/specimen\/Noto+Sans\">Noto Sans<\/a> by Google, License: SIL OFL<\/li>\n<li><a href=\"https:\/\/fonts.google.com\/specimen\/Overpass+Mono\">Overpass Mono<\/a> by Delve Withrington, License: SIL OFL<\/li>\n<li><a href=\"https:\/\/fontawesome.com\/license\">Font Awesome Free 6.7.2<\/a> by Fonticons, Inc., Font: SIL OFL 1.1 \/ Code: MIT<\/li>\n<\/ul>\n\n<h3>Minimum Requirements<\/h3>\n\n<ul>\n<li>WordPress 5.0 or higher<\/li>\n<li>PHP 7.4 or higher<\/li>\n<li>MySQL 8.0+ or MariaDB 10.5+<\/li>\n<\/ul>\n\n<p><strong>Tip:<\/strong> Install <a href=\"https:\/\/wordpress.org\/plugins\/regenerate-thumbnails\/\">Regenerate Thumbnails<\/a> and regenerate your thumbnails after activation to ensure the post listing layout renders correctly.<\/p>\n\n<h3>Automatic Installation (Recommended)<\/h3>\n\n<ol>\n<li>Log in to your WordPress admin panel.<\/li>\n<li>Navigate to <strong>Plugins -&gt; Add New<\/strong>.<\/li>\n<li>Search for <strong>AMP WP<\/strong>.<\/li>\n<li>Click <strong>Install Now<\/strong>, then <strong>Activate<\/strong>.<\/li>\n<li>Go to <strong>AMP WP -&gt; Customize AMP<\/strong> to configure your settings.<\/li>\n<\/ol>\n\n<h3>Manual Installation<\/h3>\n\n<ol>\n<li>Download the plugin ZIP from the WordPress plugin repository.<\/li>\n<li>Extract the ZIP and upload the <code>amp-wp<\/code> folder to <code>\/wp-content\/plugins\/<\/code> via FTP or your hosting file manager.<\/li>\n<li>Activate the plugin from <strong>Plugins<\/strong> in your WordPress admin panel.<\/li>\n<li>Navigate to <strong>AMP WP -&gt; Customize AMP<\/strong> to begin setup.<\/li>\n<\/ol>\n\n<h3>Developer Hooks<\/h3>\n\n<p>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 <code>functions.php<\/code> or in a standalone plugin. No plugin file edits are needed.<\/p>\n\n<h4>Template Actions<\/h4>\n\n<p>These actions fire inside AMP WP's own template system. They do not use <code>wp_head<\/code> or <code>wp_footer<\/code>. Output must be valid AMP markup.<\/p>\n\n<p><strong><code>amp_wp_template_head<\/code><\/strong>\nFires inside the AMP <code>&lt;head&gt;<\/code> element. Use for custom meta tags or other head markup. AMP WP reserves priority 0 for component scripts.<\/p>\n\n<p><strong><code>amp_wp_template_head_deferred<\/code><\/strong>\nFires in <code>&lt;head&gt;<\/code> after the AMP boilerplate styles have been written. Required injection point for <code>&lt;amp-auto-ads&gt;<\/code> and any snippet that must follow the boilerplate. AMP WP's own styles and scripts output here.<\/p>\n\n<p><strong><code>amp_wp_template_body_start<\/code><\/strong>\nFires immediately after the opening <code>&lt;body&gt;<\/code> tag.<\/p>\n\n<p><strong><code>amp_wp_body_beginning<\/code><\/strong>\nFires at the start of visible body content, before the site header renders.<\/p>\n\n<p><strong><code>amp_wp_post_content_below<\/code><\/strong>\nFires directly below the post content on single post pages.<\/p>\n\n<p><strong><code>amp_wp_template_footer<\/code><\/strong>\nFires before the closing <code>&lt;\/body&gt;<\/code> tag. Priority 999 is reserved for AMP WP's output sanitizer.<\/p>\n\n<p><strong><code>amp_wp_template_enqueue_scripts<\/code><\/strong>\nUse to register additional AMP component scripts. Call <code>amp_wp_enqueue_script( $handle, $src )<\/code> inside your callback.<\/p>\n\n<p><strong><code>amp_wp_after_comment_list<\/code><\/strong>\nFires after the comment list on single post pages.<\/p>\n\n<p><strong><code>amp_wp_notifications_bar<\/code><\/strong>\nFires inside the notification\/notice bar template slot.<\/p>\n\n<p><strong><code>amp_wp_gdpr_compliance<\/code><\/strong>\nFires inside the GDPR banner template slot.<\/p>\n\n<h4>Analytics Actions<\/h4>\n\n<p>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 <code>&lt;amp-analytics&gt;<\/code> block for a provider not yet built in, or to modify the existing output before it renders.<\/p>\n\n<ul>\n<li><code>amp_wp_analytics_ga<\/code> (Google Analytics)<\/li>\n<li><code>amp_wp_analytics_fbp<\/code> (Facebook Pixel)<\/li>\n<li><code>amp_wp_analytics_sa<\/code> (Simple Analytics)<\/li>\n<li><code>amp_wp_analytics_qc<\/code> (Quantcast)<\/li>\n<li><code>amp_wp_analytics_acm<\/code> (Adobe Campaign Manager)<\/li>\n<li><code>amp_wp_analytics_cb<\/code> (Chartbeat)<\/li>\n<li><code>amp_wp_analytics_comscore<\/code> (comScore)<\/li>\n<li><code>amp_wp_analytics_yandex_metrica<\/code> (Yandex Metrica)<\/li>\n<li><code>amp_wp_analytics_afs<\/code> (AFS Analytics)<\/li>\n<li><code>amp_wp_analytics_adobe<\/code> (Adobe Analytics)<\/li>\n<\/ul>\n\n<h4>AMP Version Control Filters<\/h4>\n\n<p><strong><code>amp_wp_amp_version_exists<\/code><\/strong>\nControl whether an AMP version is served for the current request. Return <code>false<\/code> to disable AMP for that page.\nParameter: <code>(bool) $exists<\/code><\/p>\n\n<pre><code>add_filter( 'amp_wp_amp_version_exists', '__return_false' );\n<\/code><\/pre>\n\n<p><strong><code>amp_wp_template_auto_redirect<\/code><\/strong>\nEnable automatic redirection of all visitors from the non-AMP URL to the AMP URL. Default <code>false<\/code>.\nParameter: <code>(bool) $redirect<\/code><\/p>\n\n<p><strong><code>amp_wp_filter_config_list<\/code><\/strong>\nExtend the list of post types, taxonomies, and conditions where AMP is disabled site-wide.\nParameter: <code>(array) $filters<\/code><\/p>\n\n<h4>URL and Permalink Filters<\/h4>\n\n<p><strong><code>amp_wp_pre_get_permalink<\/code><\/strong>\nShort-circuit AMP permalink generation. Return any non-false value to bypass the core URL builder.\nParameters: <code>(mixed) $pre<\/code> (default false), <code>(int) $post_id<\/code><\/p>\n\n<p><strong><code>amp_wp_get_permalink<\/code><\/strong>\nFilter the final AMP URL after it has been built.\nParameters: <code>(string) $amp_url<\/code>, <code>(int) $post_id<\/code><\/p>\n\n<p><strong><code>amp_wp_url_format_filter<\/code><\/strong>\nChange the AMP URL format. Accepted values: <code>start-point<\/code> (prefix, e.g. <code>\/amp\/slug<\/code>) or <code>end-point<\/code> (suffix, e.g. <code>\/slug\/amp<\/code>).\nParameter: <code>(string) $format<\/code><\/p>\n\n<p><strong><code>amp_wp_url_excluded<\/code><\/strong>\nAdd URL paths that must never serve an AMP version.\nParameter: <code>(array) $excluded_urls<\/code><\/p>\n\n<p><strong><code>amp_wp_transformer_exclude_subdir<\/code><\/strong>\nAdd path segments that the AMP URL transformer should skip when rewriting internal links. Used internally by AMP WP for WPML and Polylang language prefixes.\nParameter: <code>(array) $exclude_dirs<\/code><\/p>\n\n<h4>Structured Data Filters (JSON-LD)<\/h4>\n\n<p>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 <code>sprintf( 'amp_wp_json_ld_%s_', $type )<\/code> and the underscore must be part of the hook name you register.<\/p>\n\n<p><strong><code>amp_wp_json_ld_config<\/code><\/strong>\nFilters the generator configuration before any schema is built.<\/p>\n\n<p>Parameter: <code>(array) $config<\/code> with keys:\n* <code>active<\/code> (bool): set <code>false<\/code> to disable the entire JSON-LD generator for the current request.\n* <code>logo<\/code> (string): Organization logo URL. When non-empty, an <code>Organization<\/code> block is emitted on every page and all Article-type schemas reference it by <code>@id<\/code>.\n* <code>posts_type<\/code> (string): Fallback schema type when <code>schema_type_for_post<\/code> is empty. Default <code>BlogPosting<\/code>.\n* <code>media_field_id<\/code> (string): Post meta key for audio\/video URL in format posts. Default <code>_featured_embed_code<\/code>.<\/p>\n\n<p>AMP WP core attaches at priority 15 to inject the branding logo. Use priority 20 or higher to override it.<\/p>\n\n<pre><code>add_filter( 'amp_wp_json_ld_config', function( $config ) { ... }, 20 );\n<\/code><\/pre>\n\n<p><strong><code>amp_wp_json_ld_organization_<\/code><\/strong>\nFilters the <code>Organization<\/code> schema array before output. Fires only when a logo is configured. Return <code>false<\/code> or an empty array to suppress the block.\nParameter: <code>(array) $data<\/code><\/p>\n\n<pre><code>add_filter( 'amp_wp_json_ld_organization_', function( $data ) { ... } );\n<\/code><\/pre>\n\n<p><strong><code>amp_wp_json_ld_website_<\/code><\/strong>\nFilters the <code>WebSite<\/code> schema array before output. Fires only on the homepage and front page.\nParameter: <code>(array) $data<\/code><\/p>\n\n<pre><code>add_filter( 'amp_wp_json_ld_website_', function( $data ) { ... } );\n<\/code><\/pre>\n\n<p><strong><code>amp_wp_json_ld_single_<\/code><\/strong>\nFilters 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.\nParameter: <code>(array) $data<\/code><\/p>\n\n<pre><code>add_filter( 'amp_wp_json_ld_single_', function( $data ) { ... } );\n<\/code><\/pre>\n\n<h4>Content and Theme Filters<\/h4>\n\n<p><strong><code>amp_wp_template_page_on_front<\/code><\/strong>\nSpecify the page ID to use as the AMP front page when a static homepage is configured.\nParameter: <code>(int) $page_id<\/code>, default 0.<\/p>\n\n<p><strong><code>amp_wp_template_show_on_front<\/code><\/strong>\nControl what displays on the AMP homepage. Accepted values: <code>posts<\/code> or <code>page<\/code>.\nParameter: <code>(string) $show_on_front<\/code><\/p>\n\n<p><strong><code>amp_wp_template_active_template<\/code><\/strong>\nOverride the active template metadata array.\nParameter: <code>(array) $template_info<\/code><\/p>\n\n<p><strong><code>amp_wp_template_set_menu_walker<\/code><\/strong>\nEnable or disable the custom sidebar menu walker for a specific nav menu location.\nParameters: <code>(bool) $use_walker<\/code>, <code>(array) $args<\/code><\/p>\n\n<p><strong><code>amp-wp-template-default-theme-mod<\/code><\/strong>\nSet default values for AMP WP Customizer options.\nParameters: <code>(mixed) $default_value<\/code>, <code>(string) $option_key<\/code><\/p>\n\n<p><strong><code>amp_wp_home_featured<\/code><\/strong>\nCustomize the <code>WP_Query<\/code> arguments used to fetch posts for the homepage featured slider.\nParameter: <code>(array) $query_args<\/code><\/p>\n\n<p><strong><code>amp_wp_get_template<\/code><\/strong>\nOverride the file path used to locate a template part.\nParameters: <code>(string) $located<\/code>, <code>(string) $file<\/code>, <code>(array) $args<\/code>, <code>(string) $template_path<\/code>, <code>(string) $default_path<\/code><\/p>\n\n<p><strong><code>amp_wp_html_dom_filter_attributes<\/code><\/strong>\nFilter an HTML element's attributes during the DOM processing pipeline.\nParameters: <code>(array) $attributes<\/code>, <code>(string) $tag_name<\/code>, <code>(array) $valid_attributes<\/code><\/p>\n\n<p><strong><code>amp_wp_style_files_{$file}<\/code><\/strong>\nFilter CSS file content before it is added to the inline <code>&lt;style amp-custom&gt;<\/code> block. <code>{$file}<\/code> is the stylesheet handle.\nParameter: <code>(string) $css<\/code><\/p>\n\n<p><strong><code>amp_wp_social_share_cache_time<\/code><\/strong>\nSet the cache duration in seconds for social share counts. Default 7200 (120 minutes).\nParameters: <code>(int) $seconds<\/code>, <code>(int) $post_id<\/code><\/p>\n\n<p><strong><code>amp_wp_social_share_count<\/code><\/strong>\nFilter social share count results after they are fetched.\nParameter: <code>(array) $results<\/code><\/p>\n\n<p><strong><code>amp_wp_gdpr_country_list<\/code><\/strong>\nCustomize the list of countries considered GDPR-compliant.\nParameter: <code>(array) $countries<\/code><\/p>\n\n<p><strong><code>amp_wp_translation_std<\/code><\/strong>\nProvide or override fallback translation strings.\nParameter: <code>(array) $translations<\/code><\/p>\n\n<h4>Admin and Settings Hooks<\/h4>\n\n<p><strong><code>amp_wp_settings_tab_menus<\/code><\/strong> (filter)\nAdd a custom tab to the AMP WP settings panel. Key is the tab slug, value is the tab label HTML.\nParameter: <code>(array) $tabs<\/code><\/p>\n\n<pre><code>add_filter( 'amp_wp_settings_tab_menus', function( $tabs ) { $tabs['my-tab'] = '&lt;span&gt;My Tab&lt;\/span&gt;'; return $tabs; } );\n<\/code><\/pre>\n\n<p><strong><code>amp_wp_settings_tab_section<\/code><\/strong> (action)\nRender the HTML content for your custom settings tab. Check <code>$_GET['tab']<\/code> to target a specific tab.<\/p>\n\n<p><strong><code>amp_wp_save_setting_sections<\/code><\/strong> (action)\nFires when the settings form is submitted. Hook here to read and save data for a custom tab.<\/p>\n\n<p><strong><code>amp_wp_save_setting_notice<\/code><\/strong> (filter)\nCustomize the \"Settings saved.\" notice text.\nParameter: <code>(string) $notice_text<\/code><\/p>\n\n<p><strong><code>amp_wp_welcome_tab_menus<\/code><\/strong> (filter)\nAdd a custom tab to the AMP WP welcome\/dashboard page.\nParameter: <code>(array) $tabs<\/code><\/p>\n\n<p><strong><code>amp_wp_welcome_tab_section<\/code><\/strong> (action)\nRender HTML content for a custom welcome page tab.<\/p>\n\n<p><strong><code>amp_wp_default_configurations<\/code><\/strong> (action)\nFires on plugin activation. Hook here to set default options for add-on plugins.<\/p>\n\n<!--section=faq-->\n<dl>\n<dt id=\"what%20is%20the%20url%20structure%20for%20amp%20pages%3F\"><h3>What is the URL structure for AMP pages?<\/h3><\/dt>\n<dd><p>AMP WP supports two URL formats:<\/p>\n\n<ol>\n<li><strong>Prefix format:<\/strong> <code>https:\/\/yoursite.com\/amp\/page-name<\/code><\/li>\n<li><strong>Suffix format:<\/strong> <code>https:\/\/yoursite.com\/page-name\/amp<\/code><\/li>\n<\/ol>\n\n<p>You can choose your preferred format from <strong>AMP WP -&gt; Settings -&gt; General<\/strong>.<\/p><\/dd>\n<dt id=\"how%20do%20i%20add%20analytics%20tracking%3F\"><h3>How do I add analytics tracking?<\/h3><\/dt>\n<dd><p>Go to <strong>AMP WP -&gt; Settings -&gt; Analytics<\/strong> 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.<\/p><\/dd>\n<dt id=\"the%20post%20listing%20layout%20looks%20broken%3A%20how%20do%20i%20fix%20it%3F\"><h3>The post listing layout looks broken: how do I fix it?<\/h3><\/dt>\n<dd><p>This is usually caused by inconsistent thumbnail sizes. Install and run <a href=\"https:\/\/wordpress.org\/plugins\/regenerate-thumbnails\/\">Regenerate Thumbnails<\/a> to normalize all image sizes.<\/p><\/dd>\n<dt id=\"does%20amp%20wp%20support%20instagram%20reels%20and%20tv%20posts%3F\"><h3>Does AMP WP support Instagram Reels and TV posts?<\/h3><\/dt>\n<dd><p>Yes. Since version 1.6.0, AMP WP supports Instagram <code>\/p\/<\/code>, <code>\/reel\/<\/code>, and <code>\/tv\/<\/code> post types natively via <code>amp-instagram<\/code>.<\/p><\/dd>\n<dt id=\"what%20prebuilt%20listing%20layouts%20are%20available%3F\"><h3>What prebuilt listing layouts are available?<\/h3><\/dt>\n<dd><p>Two layouts are included: <strong>Classic View<\/strong> and <strong>List View<\/strong>. Switch between them from <strong>AMP WP -&gt; Options Panel<\/strong>.<\/p><\/dd>\n<dt id=\"how%20do%20i%20inject%20custom%20html%20%28e.g.%2C%20ad%20codes%2C%20analytics%20snippets%29%3F\"><h3>How do I inject custom HTML (e.g., ad codes, analytics snippets)?<\/h3><\/dt>\n<dd><p>Go to <strong>Dashboard -&gt; AMP WP -&gt; Customize AMP<\/strong>. You can inject valid AMP snippets:\n* Between <code>&lt;head&gt;&lt;\/head&gt;<\/code> tags\n* Right after the <code>&lt;body&gt;<\/code> opening tag\n* Right before the <code>&lt;\/body&gt;<\/code> closing tag<\/p>\n\n<p>Only valid, AMP-compatible code will function on AMP pages.<\/p><\/dd>\n<dt id=\"how%20do%20i%20enable%20adsense%20auto%20ads%20for%20amp%3F\"><h3>How do I enable AdSense Auto Ads for AMP?<\/h3><\/dt>\n<dd><p><strong>Recommended path (AMP WP 1.7.7 and later):<\/strong><\/p>\n\n<ol>\n<li>Open <strong>Dashboard -&gt; AMP WP -&gt; Settings -&gt; General<\/strong>.<\/li>\n<li>Scroll to the <strong>Google Auto Ads<\/strong> section.<\/li>\n<li>Tick the <strong>Enable Google Auto Ads<\/strong> checkbox and click <strong>Save Changes<\/strong>.<\/li>\n<\/ol>\n\n<p>When the toggle is on, AMP WP automatically takes care of both halves that AdSense Auto Ads needs on every AMP page:<\/p>\n\n<ul>\n<li>The <code>amp-auto-ads<\/code> runtime loader (<code>&lt;script async custom-element=\"amp-auto-ads\" src=\"https:\/\/cdn.ampproject.org\/v0\/amp-auto-ads-0.1.js\"&gt;&lt;\/script&gt;<\/code>) is injected inside <code>&lt;head&gt;<\/code> via the canonical AMP component pipeline.<\/li>\n<li>The matching <code>&lt;amp-auto-ads type=\"adsense\" data-ad-client=\"ca-pub-XXXXXXXXXXXXXXXX\"&gt;<\/code> element is emitted right after <code>&lt;body&gt;<\/code> so the AMP validator sees the extension as \"used\" and AdSense can place anchor, vignette, and in-page ads.<\/li>\n<\/ul>\n\n<p><strong>Where does the publisher ID come from?<\/strong><\/p>\n\n<ul>\n<li><strong>With Google Site Kit installed and AdSense connected:<\/strong> the publisher ID is read automatically from Site Kit's stored AdSense module setting (no extra typing needed).<\/li>\n<li><p><strong>Without Site Kit:<\/strong> supply your <code>ca-pub-...<\/code> value via the <code>amp_wp_adsense_publisher_id<\/code> filter. Drop this into your theme's <code>functions.php<\/code> or a small mu-plugin:<\/p>\n\n<p>add_filter( 'amp_wp_adsense_publisher_id', function() { return 'ca-pub-XXXXXXXXXXXXXXXX'; } );<\/p><\/li>\n<\/ul>\n\n<p>The filter accepts any of the three plausible input shapes - <code>ca-pub-XXXX<\/code>, <code>pub-XXXX<\/code>, or the bare numeric ID - and AMP WP normalises the value before output. If no publisher ID is resolvable, AMP WP silently skips the body-side element so the page stays validator-clean.<\/p>\n\n<p><strong>Manual fallback (non-AdSense ad networks, custom snippets):<\/strong><\/p>\n\n<p>Navigate to <strong>Dashboard -&gt; AMP WP -&gt; Customize AMP<\/strong>. Paste the runtime loader script in the <em>\"Codes between <code>&lt;head&gt;<\/code> and <code>&lt;\/head&gt;<\/code> tags\"<\/em> field, and your <code>&lt;amp-auto-ads&gt;<\/code> (or other AMP-valid ad markup) in the <em>\"Codes right after <code>&lt;body&gt;<\/code> tag\"<\/em> field. When you later enable the native <strong>Google Auto Ads<\/strong> toggle, AMP WP auto-cleans any manually-pasted <code>amp-auto-ads<\/code> loader from the head-code field and surfaces a one-shot admin notice confirming the cleanup, so the native injection path remains the single source of truth.<\/p>\n\n<p><a href=\"https:\/\/support.google.com\/adsense\/answer\/9011465\">AdSense Auto Ads for AMP - Google Help<\/a><\/p><\/dd>\n<dt id=\"how%20do%20i%20enable%20or%20disable%20amp%20for%20a%20specific%20post%3F\"><h3>How do I enable or disable AMP for a specific post?<\/h3><\/dt>\n<dd><p>Edit the post in WordPress, scroll to the <strong>AMP WP<\/strong> meta box in the sidebar, and toggle the AMP option on or off for that individual post.<\/p><\/dd>\n<dt id=\"how%20do%20i%20report%20a%20bug%20or%20request%20a%20feature%3F\"><h3>How do I report a bug or request a feature?<\/h3><\/dt>\n<dd><p>Please email <code>mohsin.rafique@gmail.com<\/code> or open a thread on the <a href=\"https:\/\/wordpress.org\/support\/plugin\/amp-wp\/\">WordPress support forum<\/a>.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.7.8 - 2026-05-14<\/h4>\n\n<ul>\n<li>AMP-Validity: emit the <code>&lt;amp-auto-ads type=\"adsense\" data-ad-client=\"ca-pub-XXXX\"&gt;<\/code> body-side element whenever the General Settings \"Google Auto Ads\" toggle is on and an AdSense publisher ID is resolvable. Closes the validator error \"The extension 'amp-auto-ads' was found on this page, but is unused. Please remove this extension.\" that surfaced when the toggle was enabled alongside Google Site Kit: Site Kit's AdSense AMP integration only fires for the official Automattic AMP plugin (it detects <code>amp_is_request()<\/code> \/ <code>AMP__VERSION<\/code> \/ the <code>amp_post_template_footer<\/code> hook), so on AMP WP routes Site Kit never injected the body element that the runtime loader expects to consume. AMP WP now emits the element itself. Publisher ID resolution chain: (1) <code>amp_wp_adsense_publisher_id<\/code> filter for theme\/plugin overrides, (2) Site Kit's stored AdSense module setting <code>googlesitekit_adsense_settings['clientID']<\/code> - the same key already inspected by <code>amp_wp_is_site_kit_adsense_active()<\/code>. Returned value is normalised to <code>ca-pub-XXXXXXXXXXXXXXXX<\/code>, accepting any of the three plausible input shapes (<code>ca-pub-XXXX<\/code>, <code>pub-XXXX<\/code>, or the bare numeric ID). When no publisher ID is configured anywhere the element is silently skipped so the page stays validator-clean, and when the toggle is off neither the loader nor the element is emitted. New public API: function <code>amp_wp_get_adsense_publisher_id()<\/code>, function <code>amp_wp_render_auto_ads_element()<\/code>, filter <code>amp_wp_adsense_publisher_id<\/code>. Runtime path: <code>amp_wp_render_auto_ads_element()<\/code> hooks <code>amp_wp_template_body_start<\/code> at priority 5 (runs before <code>amp_wp_custom_code_body_start<\/code> so a manual snippet in the body-start Customizer field continues to layer on top), gates on <code>amp_wp_is_auto_ads_enabled()<\/code>, and uses <code>printf<\/code> with <code>esc_attr()<\/code> on the <code>data-ad-client<\/code> value. No new option storage and no UI field added in this round (publisher ID is auto-resolved from Site Kit, or a filter override): cleanest possible diff that fixes the validator error without scope-creep into an Ads-Manager-style settings UI, which belongs in the <code>amp-wp-ads-manager<\/code> add-on.<\/li>\n<\/ul>\n\n<h4>1.7.7 - 2026-05-14<\/h4>\n\n<ul>\n<li>Feature: native \"Google Auto Ads\" toggle on the AMP WP &gt; Settings &gt; General page. When enabled, AMP WP enqueues the canonical <code>amp-auto-ads<\/code> runtime loader (<code>https:\/\/cdn.ampproject.org\/v0\/amp-auto-ads-0.1.js<\/code>) on every AMP page via the existing <code>amp_wp_enqueue_script()<\/code> registry, replacing the long-standing workaround of pasting the script into the Customizer's \"Codes between  and  tags\" field. Default off; opt-in. Runtime path: <code>amp_wp_enqueue_auto_ads_script()<\/code> is hooked on the existing <code>amp_wp_template_enqueue_scripts<\/code> action and calls <code>amp_wp_enqueue_script( 'amp-auto-ads', 'https:\/\/cdn.ampproject.org\/v0\/amp-auto-ads-0.1.js' )<\/code> - identical pattern to how every other AMP component loader is registered (<code>amp-form<\/code>, <code>amp-consent<\/code>, <code>amp-geo<\/code>, etc.), so the resulting <code>&lt;script async custom-element=\"amp-auto-ads\" src=\"...\"&gt;&lt;\/script&gt;<\/code> tag is rendered by the same <code>amp_wp_print_scripts()<\/code> callback that emits every other component and benefits from automatic dedupe against any sibling caller that registers the same handle. Backward compatibility: when the head-code Customizer field already contains an <code>amp-auto-ads<\/code> loader, the enqueue is skipped (duplicate guard via <code>amp_wp_head_field_has_auto_ads_loader()<\/code>); on save, AMP WP also strips that manually-pasted loader from the head-code field via <code>amp_wp_auto_ads_strip_manual_loader()<\/code> so the native path becomes the single source of truth, surfacing a one-shot dismissible admin notice confirming the cleanup. The settings UI shows two contextual notices: an amber heads-up when the head-code field still contains a loader (preview of what enabling the toggle will clean up) and a blue recommendation when Google Site Kit is detected active with AdSense connected (<code>amp_wp_is_site_kit_adsense_active()<\/code> checks <code>is_plugin_active( 'google-site-kit\/google-site-kit.php' )<\/code> plus the AdSense module's stored <code>clientID<\/code> in <code>googlesitekit_adsense_settings<\/code>). New helpers: <code>amp_wp_is_auto_ads_enabled()<\/code>, <code>amp_wp_is_site_kit_adsense_active()<\/code>, <code>amp_wp_head_field_has_auto_ads_loader()<\/code>, <code>amp_wp_enqueue_auto_ads_script()<\/code>, <code>amp_wp_auto_ads_strip_manual_loader()<\/code>. Migration logic hooks both <code>update_option_amp_wp_general_settings<\/code> (subsequent saves) and <code>add_option_amp_wp_general_settings<\/code> (first-ever save where the option does not yet exist - WordPress fires <code>add_option_&lt;name&gt;<\/code> instead of <code>update_option_&lt;name&gt;<\/code> in that branch). New option key <code>amp_wp_general_settings['google_auto_ads']<\/code> (boolean 0\/1); save handler always writes a 0\/1 explicitly even when the checkbox is unchecked, so the off-transition is recorded in <code>$new_value<\/code> for the migration diff. No public-API breakage; existing manually-pasted loaders in the head-code Customizer field continue to work unchanged when the toggle is left off.<\/li>\n<li>Fix: amp-geo \"country ... not valid, will be ignored\" runtime error on every page with the GDPR consent banner enabled. The <code>ISOCountryGroups.eu<\/code> array inside the <code>&lt;amp-geo&gt;<\/code> JSON config was being emitted through <code>esc_js()<\/code>, which is the wrong tool for JSON content: it HTML-encodes <code>\"<\/code> as <code>&amp;quot;<\/code>, so amp-geo received a single corrupted string like <code>PK\",\"AT\",\"BE\",...,\"CH\"<\/code> instead of an array of ISO country codes, and silently rejected the whole config (breaking geo-gated consent behaviour). Replaced the <code>esc_js( implode( '\",\"', ... ) )<\/code> pattern at <code>public\/partials\/tez\/components\/gdpr\/gdpr.php:22<\/code> with <code>wp_json_encode( array_values( array_map( 'sanitize_text_field', $gdpr_countries ) ) )<\/code> so the country list is emitted as a valid JSON array. The <code>amp_wp_gdpr_country_list<\/code> filter contract is unchanged.<\/li>\n<li>Refactor: WordPress Coding Standards (WPCS) cleanup of the Tez theme directory (<code>public\/partials\/tez\/<\/code>). All 37 template files now pass <code>phpcs --standard=WordPress<\/code> with zero errors and zero warnings, down from 49 errors and 31 warnings across 28 files. Highlights: every inline <code>\/\/<\/code> comment now ends with proper punctuation; all loose-comparison toggle checks like <code>'1' == $foo_switch<\/code> are replaced with <code>! empty( $foo_switch )<\/code> (handles both string <code>'1'<\/code> and integer <code>1<\/code> saved values uniformly without behaviour change); the file-level docblock is present and correctly spaced on every template (added to <code>header.php<\/code>, <code>footer.php<\/code>, <code>shortcodes\/amp-slider.php<\/code>, <code>shortcodes\/gallery.php<\/code>, and <code>shortcodes\/index.php<\/code>; corrected spacing on seven existing docblocks that were flush against the next code line); template-local variables that shadowed WP globals were renamed (<code>$id<\/code> -&gt; <code>$slider_id<\/code> \/ <code>$thumbnail_wrapper_id<\/code> \/ <code>$related_item_id<\/code>, <code>$link<\/code> -&gt; <code>$comment_link<\/code>, <code>$title<\/code> -&gt; <code>$archive_title<\/code>); Yoda conditions applied in <code>components\/social-list\/social-share.php<\/code>; assignments lifted out of <code>if<\/code> conditions in <code>attachment.php<\/code> and <code>social-share.php<\/code>; dead commented-out Google Plus social-share scaffolding (a service Google retired in 2019) removed from <code>components\/social-list\/social-links.php<\/code>; the slider's <code>meta_query<\/code> for featured-image gating is annotated with <code>\/\/ phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query<\/code> + justification rather than restructured (no equivalent rewrite exists without changing semantics). All changes are sniff-driven cleanups with no rendering behaviour change.<\/li>\n<li>Refactor: removed <code>public\/partials\/tez\/amp-wp-ads-manager\/ads.php<\/code> and its parent directory from core. The file (a half-completed placement-manager UI sketch from an earlier design - never <code>require<\/code>-d anywhere, hooks two filters that are never fired, calls two helper functions that are not defined) was relocated verbatim to the <code>amp-wp-ads-manager<\/code> add-on at <code>includes\/placement-manager\/ads.php<\/code> to preserve its design intent for future completion in the right plugin. Reinforces the family architecture rule that core no longer references any add-on slug in any directory path; no public-API change, no add-on consumed the file from this location.<\/li>\n<\/ul>\n\n<h4>1.7.6 - 2026-05-12<\/h4>\n\n<p><strong>Security<\/strong><\/p>\n\n<ul>\n<li>Comprehensive WordPress Coding Standards security sweep across the entire plugin. Output escaping (<code>esc_html<\/code>, <code>esc_attr<\/code>, <code>esc_url<\/code>, <code>wp_kses<\/code>, <code>wp_kses_post<\/code>) applied to every flagged <code>echo<\/code> \/ <code>printf<\/code> site in admin partials, settings forms, public templates, customizer controls, and core functions. Superglobal reads (<code>$_SERVER['REQUEST_URI']<\/code>, <code>$_SERVER['SCRIPT_FILENAME']<\/code>, <code>$_SERVER['PHP_SELF']<\/code>, <code>$_SERVER['HTTP_USER_AGENT']<\/code>, <code>$_SERVER['SERVER_SOFTWARE']<\/code>, <code>$_SERVER['LOCAL_ADDR']<\/code>, <code>$_SERVER['SERVER_ADDR']<\/code>) now consistently guarded with <code>isset()<\/code> and run through <code>esc_url_raw( wp_unslash() )<\/code> or <code>sanitize_text_field( wp_unslash() )<\/code> as appropriate per use site. Translation strings with intentional HTML (e.g. <code>&lt;strong&gt;<\/code> for inline emphasis) now route through <code>wp_kses_post( __() )<\/code> instead of bare <code>_e()<\/code> so the markup is preserved while bot-injected HTML is filtered out. Legacy <code>\/\/ WPCS: XSS ok.<\/code> comments replaced with modern <code>\/\/ phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped --<\/code> annotations with a one-line justification each. Net effect: the <code>WordPress.Security.EscapeOutput<\/code>, <code>WordPress.Security.NonceVerification<\/code>, and <code>WordPress.Security.ValidatedSanitizedInput<\/code> sniffs report 0 errors and 0 warnings across the plugin (down from 311 errors before the sweep). Total WPCS reduction: 1,448 -&gt; 632 (56%). No behavioural change - all edits are escaping\/sanitizing additions or <code>phpcs:ignore<\/code> annotations on canonical safe-output patterns.<\/li>\n<\/ul>\n\n<p><strong>Added<\/strong><\/p>\n\n<ul>\n<li>New \"Premium Extensions\" tab on the AMP WP Settings page (<code>admin.php?page=amp-wp-settings#settings-premium-extensions<\/code>). 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 <code>amp_wp_premium_extensions_section<\/code> action - callbacks echo a card (heading + <code>form-table<\/code> row group) inside the tab body, and the existing <code>amp_wp_save_setting_sections<\/code> action persists each add-on's option independently. New files: <code>includes\/admin\/settings\/class-amp-wp-premium-extensions.php<\/code> (registers the tab) and <code>admin\/partials\/settings\/amp-wp-admin-premium-extensions.php<\/code> (the form scaffold).<\/li>\n<li>Premium-extension registration API: <code>amp_wp_register_premium_extension( string $slug, array $args = [] ): void<\/code>, <code>amp_wp_get_registered_premium_extensions(): array&lt;string,array&lt;string,string&gt;&gt;<\/code>, and <code>amp_wp_has_active_premium_extension(): bool<\/code> (all in <code>includes\/functions\/amp-wp-core-functions.php<\/code>). Each AMP WP family add-on self-registers once on bootstrap with a slug + display metadata (<code>name<\/code>, <code>description<\/code>, <code>version<\/code>, <code>url<\/code>). Idempotent: registering the same slug twice is a no-op. New companion filter <code>amp_wp_premium_extensions<\/code> 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\").<\/li>\n<li>Template-path registration: new public functions <code>amp_wp_register_template_path( string $absolute_path ): void<\/code> and <code>amp_wp_get_registered_template_paths(): array<\/code> (in <code>includes\/functions\/amp-wp-theme-functions.php<\/code>) 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 <code>&lt;wp-theme&gt;\/amp-wp\/&lt;template&gt;<\/code> (site override - unchanged) -&gt; registered add-on paths in registration order -&gt; core's Tez directory as the catch-all fallback. End-user override convention preserved verbatim. New filter <code>amp_wp_template_paths<\/code> lets advanced users reorder or suppress paths per-request. Companion change in <code>amp-wp-woocommerce<\/code> migrates eight WC-specific AMP partials out of core to restore the family architecture rule \"Core never references any add-on by name\".<\/li>\n<li>New extension hook <code>amp_wp_layout_setting_after_show_comments<\/code> fires inside the Layout Settings -&gt; Single Post Page table, immediately after the \"Show Comments\" <code>&lt;tr&gt;<\/code>. 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 <code>admin\/partials\/settings\/amp-wp-admin-layout.php<\/code>. Callbacks must echo a complete <code>&lt;tr&gt;...&lt;\/tr&gt;<\/code> matching the surrounding form-table markup; inputs may piggyback on the existing <code>amp_wp_layout_settings[...]<\/code> name prefix to persist via the existing save handler at <code>Amp_WP_Layout::amp_wp_save_layout_settings()<\/code> - no separate option, no separate save flow.<\/li>\n<\/ul>\n\n<p><strong>Changed<\/strong><\/p>\n\n<ul>\n<li>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 <code>amp_wp_register_premium_extension()<\/code> 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 <code>amp_wp_premium_extensions_section<\/code> 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 <code>#settings-premium-extensions<\/code> no longer paints orphaned form markup either.<\/li>\n<\/ul>\n\n<p><strong>Fixed<\/strong><\/p>\n\n<ul>\n<li>Browsers fetching <code>\/favicon.ico<\/code> (and any other root-level static-file URL) on mobile no longer trigger a 404. <code>Amp_WP_Public::amp_wp_auto_redirect_to_amp()<\/code> fed <code>$_SERVER['REQUEST_URI']<\/code> through <code>Amp_WP_Content_Sanitizer::transform_to_amp_url()<\/code>, which blindly appended <code>\/amp<\/code> to any internal URL it didn't already recognise as an AMP path or wp-content asset. When a site has no static <code>favicon.ico<\/code> file at the document root, the browser-issued favicon request fell through to <code>index.php<\/code>, hit <code>template_redirect<\/code> on mobile, and the auto-redirect bounced the browser to <code>\/favicon.ico\/amp<\/code> - which never matches a rewrite rule and 404s. Same shape would fire for any root-level static file (<code>sitemap.xml<\/code>, <code>robots.txt<\/code>, <code>ads.txt<\/code>, <code>manifest.json<\/code>, etc.) when no physical file exists. Fix: <code>transform_to_amp_url()<\/code> 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 <code>amp_wp_non_amp_url_extensions<\/code> filter so unusual extensions can be added per-site. Case-insensitive match. Side benefit: every other call site of <code>transform_to_amp_url()<\/code> - filters on <code>term_link<\/code>, <code>author_link<\/code>, <code>attachment_link<\/code>, <code>post_type_link<\/code>, the nav-menu <code>href<\/code> 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.<\/li>\n<li>Search-engine crawlers no longer get caught by the mobile auto-redirect to AMP. <code>Amp_WP_Public::amp_wp_auto_redirect_to_amp()<\/code> previously checked only <code>wp_is_mobile()<\/code>, which returns true for Googlebot-Mobile, Bingbot, YandexBot, DuckDuckBot, AppleBot, FacebookExternalHit, Twitterbot, LinkedInBot, Slurp, AhrefsBot, and SemrushBot. Each was being 302-redirected from <code>https:\/\/yoursite.com\/<\/code> to <code>https:\/\/yoursite.com\/amp\/<\/code>; the AMP page's <code>&lt;link rel=\"canonical\"&gt;<\/code> 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 <code>&lt;link rel=\"amphtml\"&gt;<\/code>, not a UA redirect. Fix: new public helper <code>amp_wp_is_search_engine_bot(): bool<\/code> in <code>includes\/functions\/amp-wp-core-functions.php<\/code> checks <code>HTTP_USER_AGENT<\/code> 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 <code>amp_wp_search_engine_bot_user_agents<\/code> (UA fragment list) and <code>amp_wp_is_search_engine_bot<\/code> (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.<\/li>\n<li>Pagination on AMP archives was broken for any URL of the form <code>\/&lt;archive&gt;\/amp\/page\/N\/<\/code>. The URL-based branch of <code>is_amp_wp()<\/code> (used during <code>pre_get_posts<\/code> before <code>template_redirect<\/code> fires, when the <code>amp<\/code> query var is not yet set on <code>$wp_query<\/code>) only matched the AMP token at the very start or very end of the request URI - so <code>\/shop\/amp\/page\/2\/<\/code>, <code>\/product-category\/&lt;slug&gt;\/amp\/page\/2\/<\/code>, <code>\/category\/&lt;slug&gt;\/amp\/page\/2\/<\/code>, <code>\/tag\/&lt;slug&gt;\/amp\/page\/2\/<\/code>, and <code>\/&lt;page&gt;\/amp\/comment-page-N\/<\/code> all returned <code>false<\/code>. The cascade was severe: any third-party <code>pre_get_posts<\/code> callback gated on <code>is_amp_wp()<\/code> (notably the AMP WP - WooCommerce add-on's priority-0 bridge that re-registers <code>WC_Query::pre_get_posts<\/code> at priority 101) bailed early, AMP WP's query isolation between priorities 1 and 100 wiped WooCommerce's product-archive setup, and <code>\/shop\/amp\/page\/2\/<\/code> rendered the shop <em>page<\/em> (post type <code>page<\/code>, ID 588) with <code>paged=2<\/code> instead of the products grid. The old second regex also had a separate false-positive bug where <code>amp\/*<\/code> allowed zero trailing characters and matched URIs like <code>\/ampersand\/<\/code> and <code>\/amp-tree\/<\/code>. Both regexes replaced with a single boundary-anchored pattern <code>#(?:^|\/)&lt;amp&gt;(?:\/|$)#<\/code> 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 <code>\/shop\/amp\/page\/2\/<\/code>: <code>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<\/code> (was <code>post_count=1 paged=2 post_type=\"\" is_archive=0 is_page=1 is_amp_wp=0<\/code> before the fix).<\/li>\n<li>The \"Premium Extensions\" tab was rendering an empty <code>&lt;i&gt;<\/code> tag with no visible icon next to the label. The original <code>amp-wp-admin-icon-star<\/code> class did not exist in <code>admin\/css\/amp-wp-admin.css<\/code> or in the icon font at <code>admin\/fonts\/amp-wp-admin-icons\/<\/code>. Switched to <code>amp-wp-admin-icon-feather<\/code>, 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.<\/li>\n<\/ul>\n\n<p><strong>Docs<\/strong><\/p>\n\n<ul>\n<li>Inline help text added to five settings tabs: Structured Data, GDPR Compliance, Notice Bar, Layout Settings, and General Settings. Around 30 new <code>&lt;p class=\"description\"&gt;<\/code> 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 <code>esc_html_e( ..., 'amp-wp' )<\/code> using the same <code>&lt;p class=\"description\"&gt;<\/code> pattern already established by the GDPR partial. No PHP \/ behaviour changes - pure documentation in the admin UI.<\/li>\n<li>Inline help text added under the OneSignal options on the 3rd Party Plugins tab (<code>admin.php?page=amp-wp-settings#settings-third-party-plugins-support<\/code>). Three new <code>&lt;p class=\"description\"&gt;<\/code> blocks: under \"App ID\" (UUID format and where to find it - OneSignal dashboard -&gt; Settings -&gt; Keys &amp; 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 <code>yoursite.os.tc<\/code> that non-HTTPS sites need for the push subscription frame; HTTPS sites should leave the field blank).<\/li>\n<\/ul>\n\n<h4>1.7.5 - 2026-05-07<\/h4>\n\n<ul>\n<li>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 <code>301 Moved Permanently<\/code> to <code>302 Found<\/code> and emit <code>nocache_headers()<\/code>, 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 <code>DONOTCACHEPAGE<\/code> 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 <code>Clear-Site-Data: \"cache\"<\/code> header (HTTPS-only, gated by an <code>amp_wp_cache_cleared<\/code> cookie marker so normal HTTP caching is preserved on subsequent redirects), which evicts any stale <code>301<\/code> pinned in the mobile browser before it follows the redirect.<\/li>\n<li>Fixed: <code>amp-state<\/code> elements are no longer stripped from AMP pages when the AMP WP Comments plugin is active. The content sanitizer's allowed-tag list (<code>tags-list.php<\/code>) did not include <code>amp-state<\/code>, 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.<\/li>\n<li>Fixed: Per-comment Reply links now appear in threaded comment lists on AMP pages. <code>amp_wp_comment_item()<\/code> was not forwarding the <code>$depth<\/code> argument from <code>wp_list_comments()<\/code> to the <code>comment-item.php<\/code> template. WordPress 6.8 updated <code>get_comment_reply_link()<\/code> to return null when depth is 0, so every reply link resolved to nothing. The function now accepts and passes <code>$depth<\/code> (defaulting to 1).<\/li>\n<li>Fixed: Per-comment Reply button now shows the label \"Reply\" instead of the comment form title \"Leave a Reply\". The template was pulling from <code>amp_wp_translation_get('comments_reply')<\/code>, which returns the form heading. The button now uses <code>__('Reply', 'amp-wp')<\/code> directly.<\/li>\n<li>Fixed: AFS Analytics configuration JSON was malformed. Missing commas after <code>websiteid<\/code> and <code>title<\/code> properties caused a JSON parse error in the AMP runtime, silently disabling analytics on AMP pages when AFS Analytics was configured.<\/li>\n<li>Improved: <code>includes\/class-amp-wp-redirect-router.php<\/code> brought into WordPress Coding Standards compliance. Added a proper file-level docblock (the previous one only documented the class). Sanitized <code>$_SERVER['REQUEST_URI']<\/code> via <code>isset()<\/code> + <code>esc_url_raw( wp_unslash() )<\/code> in <code>redirect_to_amp_url()<\/code>. Renamed the singleton accessor <code>Run()<\/code> to <code>run()<\/code> 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 <code>Amp_WP_Public::define_public_hooks()<\/code> was updated. None of the six add-ons (cf7, comments, woocommerce, wpforms, gf, ads-manager) reference the class.<\/li>\n<li>Improved: <code>public\/class-amp-wp-public.php<\/code> brought into WordPress Coding Standards compliance. Sanitized and unslashed all <code>$_SERVER['REQUEST_URI']<\/code> and <code>$_SERVER['HTTP_HOST']<\/code> reads via <code>esc_url_raw( wp_unslash() )<\/code> \/ <code>sanitize_text_field( wp_unslash() )<\/code> with <code>isset()<\/code> guards in <code>redirect_to_start_point_amp()<\/code>, <code>redirect_to_end_point_amp()<\/code>, and <code>amp_wp_get_requested_page_url()<\/code>. Switched all internal same-origin redirects from <code>wp_redirect()<\/code> to <code>wp_safe_redirect()<\/code>. Replaced loose <code>==<\/code> comparisons with strict <code>===<\/code> in <code>amp_wp_transform_post_link_to_amp()<\/code>, <code>amp_wp_init_json_ld()<\/code>, and <code>is_amp_excluded_by_url()<\/code>; added <code>true<\/code> strict flag to all <code>in_array()<\/code> calls in <code>amp_version_exists()<\/code>. Refactored the empty-body if\/elseif assignment-in-condition chain in <code>amp_wp_template_loader()<\/code> 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 <code>prepend_attachment<\/code> filter removal. Renamed the private helper <code>_amp_wp_can_call_component_method()<\/code> to drop the leading underscore (visibility is already encoded in the <code>private<\/code> keyword) and removed its unused <code>&amp;$args<\/code> reference parameter; the single internal caller was updated to match. Renamed the <code>$default<\/code> parameter on <code>amp_wp_get_option()<\/code> to <code>$default_value<\/code> to avoid the PHP reserved-keyword shadow. Filled in 19 missing or incomplete <code>@param<\/code> 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.<\/li>\n<li>Added: <code>tools\/test-redirects.sh<\/code> - 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: <code>BASE_URL=https:\/\/your-site.com .\/tools\/test-redirects.sh<\/code>. 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, <code>Cache-Control: no-cache<\/code> + <code>no-store<\/code>, <code>Clear-Site-Data: \"cache\"<\/code> presence\/absence per cookie state, hardened <code>Set-Cookie<\/code> 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.<\/li>\n<\/ul>\n\n<h4>1.7.4 - 2026-05-01<\/h4>\n\n<ul>\n<li>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 <code>wp_kses_post()<\/code>, which strips non-standard HTML elements including <code>&lt;amp-img&gt;<\/code> and <code>&lt;amp-anim&gt;<\/code>. The logo tag was silently removed on every page load, leaving an empty link in the header. A dedicated <code>amp_wp_kses_amp_img()<\/code> helper now sanitizes logo output using <code>wp_kses()<\/code> with <code>amp-img<\/code> and <code>amp-anim<\/code> added to the allowed-tag list, preserving <code>src<\/code>, <code>width<\/code>, <code>height<\/code>, <code>class<\/code>, <code>alt<\/code>, <code>sizes<\/code>, <code>layout<\/code>, and <code>on<\/code> attributes.<\/li>\n<li>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.<\/li>\n<li>Fixed: Notice Bar and GDPR Compliance no longer silently fail to appear on AMP pages. Both save functions stored the enabled switch as integer <code>1<\/code> while the frontend callbacks checked for string <code>'1'<\/code> with strict <code>===<\/code> comparison, causing the condition to always evaluate false and neither component to render regardless of the saved setting.<\/li>\n<li>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 <code>amp_wp_settings_nonce<\/code> token used across all settings tabs, and the save function validates it before processing POST data.<\/li>\n<li>Fixed: Notice Bar accept button text field incorrectly fell back to an empty <code>array()<\/code> instead of an empty string when no value was saved, causing a type mismatch when the value was passed to <code>esc_attr()<\/code>.<\/li>\n<li>Fixed: GDPR <code>wp_dropdown_pages()<\/code> arguments <code>show_option_no_change<\/code> and <code>option_none_value<\/code> were explicitly set to <code>null<\/code>, overriding WordPress defaults and generating PHP 8 type deprecation warnings. Both are now set to empty strings.<\/li>\n<li>Fixed: GDPR consent form accept and reject actions no longer silently fail to redirect after submission. Both <code>AMP-Access-Control-Allow-Source-Origin<\/code> and <code>AMP-Redirect-To<\/code> response headers had a trailing space appended to their values, causing header parsing failures in the AMP runtime.<\/li>\n<li>Fixed: \"Privacy Settings\" re-open button label in the GDPR post-consent UI was a hardcoded English string. It is now wrapped with <code>__()<\/code> and translatable.<\/li>\n<\/ul>\n\n<h4>1.7.3 - 2026-04-30<\/h4>\n\n<ul>\n<li>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.<\/li>\n<li>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.<\/li>\n<li>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.<\/li>\n<li>Fixed: Homepage title sync with Yoast SEO now works on AMP front pages with Yoast v14+ using YoastSEO()-&gt;meta-&gt;for_post(). Previously the function fell through silently on modern Yoast because the WPSEO_Frontend::get_instance() guard evaluated to false.<\/li>\n<li>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.<\/li>\n<li>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()-&gt;head-&gt;output() to render the full meta block, while retaining the legacy v3 code path as a fallback.<\/li>\n<li>Fixed: AIOSEO homepage title sync now works on v4+ using aioseo()-&gt;meta-&gt;title-&gt;getPostTitle(). The previous call used a non-existent get() method and silently returned no title on all modern AIOSEO versions.<\/li>\n<li>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.<\/li>\n<li>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.<\/li>\n<li>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.<\/li>\n<li>Fixed: Structured data schema type (<code>schema_type_for_post<\/code>) is now validated against the allowed set (<code>Article<\/code>, <code>NewsArticle<\/code>, <code>BlogPosting<\/code>) before being passed to the JSON-LD generator. A tampered or corrupted database value could previously write an arbitrary <code>@type<\/code> string into the JSON-LD output, producing invalid structured data that fails Google's Rich Results validator.<\/li>\n<li>Fixed: <code>datePublished<\/code> and <code>dateModified<\/code> in JSON-LD structured data now use ISO 8601 datetime format with timezone offset (<code>DATE_ATOM<\/code>, e.g. <code>2024-01-15T10:30:00+05:00<\/code>) instead of date-only format (<code>Y-m-d<\/code>). The previous date-only format omits time and timezone information, which is non-compliant with the Schema.org <code>DateTime<\/code> specification and reduces precision for Google's structured data parser.<\/li>\n<li>Fixed: <code>interactionStatistic.userInteractionCount<\/code> in JSON-LD structured data is now cast to integer before output. <code>get_comments_number()<\/code> returns a string; Schema.org defines <code>userInteractionCount<\/code> as a <code>Number<\/code> type, so a string value caused Google's Rich Results validator to report a type mismatch on every post.<\/li>\n<li>Fixed: <code>Article<\/code>, <code>NewsArticle<\/code>, and <code>BlogPosting<\/code> schemas now always include an <code>image<\/code> 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 <code>image<\/code> as required for all Article-type rich results: posts without a featured image previously emitted no <code>image<\/code> at all, silently disqualifying them from rich result eligibility in Google Search.<\/li>\n<li>Fixed: Yoast SEO homepage JSON-LD sync now actually fires on AMP pages. The <code>amp_wp_json_ld_website_<\/code> filter (note the trailing underscore, which is the real filter name emitted by the generator) was registered without the trailing underscore as <code>amp_wp_json_ld_website<\/code>, 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.<\/li>\n<li>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 <code>add_action<\/code> call, the <code>multi_rating()<\/code> method, and the file-header reference.<\/li>\n<li>Verified: Snip Rich Snippets (<code>rich-snippets-schema<\/code>) compatibility with AMP pages confirmed correct and complete. AMP WP's template system does not fire <code>wp_head<\/code>, so Snip's own head hook is silent on AMP pages. The compatibility layer re-routes Snip's <code>print_snippets<\/code> output to <code>amp_wp_template_head<\/code> or <code>amp_wp_template_footer<\/code> (respecting Snip's own \"snippets in footer\" setting) exactly once per request. Snip's JSON-LD output is AMP-spec-valid (<code>&lt;script type=\"application\/ld+json\"&gt;<\/code> is permitted in AMP pages) and coexists with AMP WP's own structured data blocks without duplication.<\/li>\n<li>Fixed: wpForo Forum compatibility now works correctly with wpForo 3.x. The previous detection used <code>class_exists('wpForo')<\/code>, which always returned false on wpForo 3.x because that version moved to a PHP namespace (<code>wpforo\\wpforo<\/code>). As a result, the <code>amp_wp_amp_version_exists<\/code> filter was never registered, and AMP WP silently served AMP pages on wpForo forum URLs on all modern wpForo installs. Detection now uses <code>defined('WPFORO_VERSION')<\/code>, which is reliably set by all wpForo versions.<\/li>\n<\/ul>\n\n<h4>1.7.2 - 2026-04-26<\/h4>\n\n<ul>\n<li>Fixed: Google Analytics AMP tag now correctly detects GA4 (<code>G-XXXXXXXX<\/code>) vs Universal Analytics (<code>UA-XXXXXXX-X<\/code>) IDs. GA4 IDs now output <code>&lt;amp-analytics type=\"gtag\"&gt;<\/code> with <code>gtag_id<\/code> \/ <code>config<\/code> vars, while UA IDs continue to use the legacy <code>type=\"googleanalytics\"<\/code> vendor. This resolves the persistent <code>[AmpAnalytics googleanalytics] Warning: [object Object]<\/code> console error that appeared after migrating to a GA4 Measurement ID.<\/li>\n<li>Fixed: JSON-LD structured data: 11 Schema.org \/ Google Rich Results compliance issues resolved: <code>mainEntityOfPage<\/code> is now a typed <code>WebPage<\/code> object instead of a plain URL; <code>publisher<\/code> outputs an inline <code>Organization<\/code> when no logo is configured so the <code>#organization<\/code> reference never dangles; <code>headline<\/code> capped at 110 characters per Google AMP article spec; all <code>@context<\/code> values normalised to <code>https:\/\/schema.org<\/code> (no trailing slash); all <code>@id<\/code> values upgraded to absolute URLs; <code>WebSite<\/code> schema uses <code>description<\/code> instead of <code>alternateName<\/code> for the site tagline; <code>AudioObject<\/code> now includes the required <code>name<\/code> property; <code>post_excerpt<\/code> is sanitised before output; <code>wordCount<\/code> restricted to Article sub-types only; <code>WebPage potentialAction<\/code> corrected to a direct <code>SearchAction<\/code> object; <code>JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE<\/code> added to JSON output flags.<\/li>\n<li>Fixed: AdSense Auto Ads (and any custom <code>&lt;head&gt;<\/code> code) now outputs via the <code>amp_wp_template_head_deferred<\/code> hook at  &hellip;<\/li>\n<\/ul>","raw_excerpt":"The most complete free AMP plugin for WordPress. Supercharge mobile performance with Google Accelerated Mobile Pages, no coding required.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/90521","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=90521"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/pixelative"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=90521"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=90521"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=90521"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=90521"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=90521"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=90521"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}