Skip to content

Instantly share code, notes, and snippets.

@westonruter
Last active September 4, 2020 15:51
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save westonruter/5f4f27ed3bdd676e3f08524b9bab8bb4 to your computer and use it in GitHub Desktop.
Save westonruter/5f4f27ed3bdd676e3f08524b9bab8bb4 to your computer and use it in GitHub Desktop.
[OBSOLETE] Feature plugin to implement https://github.com/ampproject/amp-wp/issues/4479
<?php
/**
* AMP Mobile JS Redirection plugin initialization file.
*
* @package AMP_Mobile_JS_Redirection
* @author Weston Ruter, Google
* @link https://gist.github.com/westonruter/5f4f27ed3bdd676e3f08524b9bab8bb4
* @license GPL-2.0-or-later
* @copyright 2019 Google Inc.
*
* @wordpress-plugin
* Plugin Name: AMP Mobile JS Redirection
* Plugin URI: https://gist.github.com/westonruter/5f4f27ed3bdd676e3f08524b9bab8bb4
* Description: Automatically redirect mobile visitors to the AMP version when the AMP plugin is in a paired mode (Reader/Transitional). This plugin depends on AMP plugin v1.5-alpha. Reader more in <a href="https://github.com/ampproject/amp-wp/issues/2044">amp-wp#2044</a>.
* Version: 0.2
* Author: Weston Ruter, Google
* Author URI: https://weston.ruter.net/
* License: GNU General Public License v2 (or later)
* License URI: http://www.gnu.org/licenses/gpl-2.0.html
* Gist Plugin URI: https://gist.github.com/westonruter/5f4f27ed3bdd676e3f08524b9bab8bb4
*/
namespace AMP_Mobile_JS_Redirection;
use WP_Post;
use WP_Query;
const DISABLE_MOBILE_REDIRECT_KEY = 'disable_mobile_redirect';
/**
* Initialize.
*/
function init() {
// Abort if the AMP plugin is is not active.
if ( ! function_exists( 'is_amp_endpoint' ) ) {
return;
}
if ( version_compare( AMP__VERSION, '1.5', '<' ) ) {
trigger_error( 'Plugin depends on AMP plugin v1.5', E_USER_NOTICE );
return;
}
// Abort if in Standard mode (AMP-first) since redirecting to the AMP version only makes sense in a paired AMP context.
if ( amp_is_canonical() ) {
return;
}
// Prevent needless redirects to mobile version after on a mobile page by forcing AMP-to-AMP linking to be enabled.
add_filter( 'amp_to_amp_linking_enabled', '__return_true' );
if ( is_amp() ) {
add_action( 'wp_footer', __NAMESPACE__ . '\add_version_switcher_link' );
add_action( 'amp_post_template_footer', __NAMESPACE__ . '\add_version_switcher_link' );
} elseif ( has_amp_version_available() ) {
add_action(
'wp_head',
__NAMESPACE__ . '\add_redirect_script',
~PHP_INT_MAX // Run the absolutely earliest as possible.
);
add_action( 'wp_footer', __NAMESPACE__ . '\add_version_switcher_link' );
}
}
add_action( 'wp', __NAMESPACE__ . '\init' );
/**
* Determine whether it is an AMP response.
*
* @return bool
*/
function is_amp() {
return function_exists( 'is_amp_endpoint' ) && is_amp_endpoint();
}
/**
* Determine whether there is an AMP version available for this URL.
*
* @return bool
* @global WP_Query $wp_query
*/
function has_amp_version_available() {
global $wp_query;
$queried_object = get_queried_object();
if ( current_theme_supports( \AMP_Theme_Support::SLUG ) ) {
// Abort if in Transitional mode and AMP is not available for the URL.
if ( ! \AMP_Theme_Support::is_paired_available() ) {
return false;
}
} elseif ( ! ( $queried_object instanceof WP_Post && $wp_query instanceof WP_Query && ( $wp_query->is_singular() || $wp_query->is_posts_page ) && post_supports_amp( $queried_object ) ) ) {
// Abort if in Reader mode and the post doesn't support AMP.
return false;
}
return true;
}
/**
* Add script as early to the page as possible to detect mobile visitors and redirect to the AMP version unless they have opted-out.
*
* This function is only called in a non-AMP context, that is in the context of the "desktop" site (non-AMP).
* Again, this assumes Reader/Transitional mode. AMP is fully capable of creating desktop experiences,
* and this is what the AMP plugin's Standard mode enables: AMP-first.
*
* @todo Need to handle the case where the AMP version redirected to the non-AMP version due to validation errors.
*/
function add_redirect_script() {
?>
<script>
(function( disableMobileRedirectKey, ampQueryParam ) {
var isMobile = /Mobile|Android|Silk\/|Kindle|BlackBerry|Opera Mini|Opera Mobi/.test( navigator.userAgent ); // See wp_is_mobile().
if ( isMobile ) {
document.addEventListener( 'DOMContentLoaded', function() {
var versionSwitchLink = document.getElementById( 'site-version-switcher' );
if ( versionSwitchLink ) {
versionSwitchLink.hidden = false;
}
} );
}
// Short-circuit if mobile redirection is disabled.
if ( '1' === sessionStorage.getItem( disableMobileRedirectKey ) ) {
return;
}
// Handle request that disables mobile redirect by storing the preference and scrubbing the URL of the param.
var url = new URL( location.href );
if ( url.searchParams.has( disableMobileRedirectKey ) ) {
url.searchParams.delete( disableMobileRedirectKey );
sessionStorage.setItem( disableMobileRedirectKey, '1' );
history.replaceState( {}, '', url.href );
return;
}
// Otherwise, if the user agent is mobile, we need to redirect them.
if ( isMobile && ! url.searchParams.has( ampQueryParam ) ) {
window.stop(); // Stop loading the page! This should cancel all loading resources.
// Replace the current page with the AMP version.
url.searchParams.append( ampQueryParam, '1' );
location.replace( url.href );
}
})(
<?php echo wp_json_encode( DISABLE_MOBILE_REDIRECT_KEY ); ?>,
<?php echo wp_json_encode( amp_get_slug() ); ?>
);
</script>
<?php
}
/**
* Add version switcher link.
*/
function add_version_switcher_link() {
global $wp_query;
$is_amp = is_amp();
if ( $is_amp ) {
$url = add_query_arg(
DISABLE_MOBILE_REDIRECT_KEY,
'1',
amp_remove_endpoint( amp_get_current_url() )
);
} else {
if ( current_theme_supports( \AMP_Theme_Support::SLUG ) ) {
if ( \AMP_Theme_Support::is_paired_available() ) {
$url = add_query_arg( amp_get_slug(), '', amp_get_current_url() );
}
} elseif ( $wp_query instanceof WP_Query && ( $wp_query->is_singular() || $wp_query->is_posts_page ) && post_supports_amp( get_post( get_queried_object_id() ) ) ) {
$url = amp_get_permalink( get_queried_object_id() );
}
}
if ( ! isset( $url ) ) {
return;
}
?>
<div
id="site-version-switcher"
<?php if ( ! $is_amp ) : ?>
hidden
<?php endif; ?>
>
<style>
#version-switch-link {
display: block;
width: 100%;
padding: 15px 0;
font-size: 16px;
font-weight: 600;
color: #eaeaea;
text-align: center;
background-color: #444;
border: 0;
}
</style>
<?php if ( $is_amp ) : ?>
<a
id="version-switch-link"
rel="noamphtml"
href="<?php echo esc_url( $url ); ?>"
>
<?php esc_html_e( 'Leave mobile version', 'amp' ); ?>
</a>
<?php else : ?>
<a
id="version-switch-link"
rel="amphtml"
href="<?php echo esc_url( $url ); ?>"
onclick="<?php echo esc_attr( sprintf( 'sessionStorage.removeItem( %s );', wp_json_encode( DISABLE_MOBILE_REDIRECT_KEY ) ) ); ?>"
>
<?php esc_html_e( 'Return to mobile version', 'amp' ); ?>
</a>
<?php endif; ?>
</div>
<?php
}
@westonruter
Copy link
Author

In addition to using window.stop(), another option could be to document.write('<plaintext>'), although plaintext is obsolete: “Do not use this element.”

@westonruter
Copy link
Author

@chuckball
Copy link

Hello,

I've just installed the plugin and met with a few issues:

The desktop link seems to link to the wrong root of my site.
e.g. site.com/extension instead of site.com/blog/extension

Also, certain posts go into a redirection loop
e.g. site.com/blog/extension/?amp=1&amp=1&amp=1&amp=1&amp=1.......

Is this a known issue? Let me know if I can furnish more information. Thanks!

Warm Regards

@westonruter
Copy link
Author

The desktop link is obtained via amp_get_current_url() which is currently:

function amp_get_current_url() {
	$url = preg_replace( '#(^https?://[^/]+)/.*#', '$1', home_url( '/' ) );
	if ( isset( $_SERVER['REQUEST_URI'] ) ) {
		$url = esc_url_raw( $url . wp_unslash( $_SERVER['REQUEST_URI'] ) );
	} else {
		$url .= '/';
	}
	return $url;
}

Is there a bug in there?

What if add_desktop_link() here was changed to define $non_amp_url as:

$non_amp_url = add_query_arg(
	DISABLE_MOBILE_REDIRECT_KEY,
	'1',
	amp_remove_endpoint( wp_unslash( $_SERVER['REQUEST_URI'] ) )
);

@westonruter
Copy link
Author

I've just pushed an update that should fix the issue with the infinite redirect issue and also improve detection for whether redirection should happen in the first place.

@chuckball
Copy link

It seems that my REQUEST_URI is returning a different root, I'll have to look into that.
The infinite redirect issue was fixed. Thanks!

@faheem864
Copy link

Why would the url have two amp's after installing it? e.g example.net/post-abc/amp/?amp

@westonruter
Copy link
Author

@faheem864 Are you in Transitional mode or Reader mode?

@westonruter
Copy link
Author

The functionality in this plugin is now part of the AMP plugin as of v2.0. Please deactivate this plugin and upgrade the AMP plugin.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment