Created
September 25, 2021 09:23
-
-
Save sabrina-zeidan/7d34eccceed18421cd49fbd225d156b1 to your computer and use it in GitHub Desktop.
Delay Intercom execution in WordPress
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Intercom plugin adds Intercom script to critical render path, sets it to be not defered | |
// And adds the script in WordPress in a way it doesn't leave much options to alter it in order to delay Intercom execution and prevent it to be render blocking | |
// Altering buffer in WP generally in not a great idea, but since we have no choice, let's make sure we are altering it in a way it doesn't break things | |
// If you use WP Rocket -- use 'rocket_buffer' filter instead | |
add_action( 'init', 'sz_buffer_process_post' ); //we use 'init' action to use ob_start() | |
function sz_buffer_process_post() { | |
ob_start(); | |
} | |
add_action('shutdown', function() { | |
$final = ''; | |
$levels = ob_get_level(); | |
for ($i = 0; $i < $levels; $i++) { | |
$final .= ob_get_contents(); | |
ob_clean(); | |
} | |
$final_output = apply_filters( 'sz_filter_final_html', $final); | |
echo $final_output; | |
}, 0); | |
// Delay Intercom by varying HTML output via buffer | |
add_filter( 'sz_filter_final_html', 'sz_filter_html_intercom', 10, 1); | |
function sz_filter_html_intercom( $html ) { | |
$current_url = home_url($_SERVER['REQUEST_URI']); | |
if (!is_admin() && !is_user_logged_in() && (strpos($current_url, 'xmlrpc.php') === false)){ | |
//these checks needed if you are not using WP Rocket buffer | |
//Main thing is here: | |
preg_match_all( '/<script.*w\.Intercom=i.*<\/script>/U', $html, $found_scripts ); //in case it is more than one occurences | |
foreach ( $found_scripts[0] as $found_script ) { | |
$replace_script = str_replace( 'data-cfasync="false"', 'defer', $found_script ); // defer loading | |
$replace_script = str_replace( "function l(){", "function l(){ setTimeout(function () {", $replace_script ); //and delay execution | |
$replace_script = str_replace( 'x.parentNode.insertBefore(s,x);', 'x.parentNode.insertBefore(s,x);}, 3000);', $replace_script ); | |
$html = str_replace( $found_script, $replace_script, $html ); | |
//Many thanks to @wppunk for helping out with this part | |
} | |
} | |
return $html; | |
} | |
/** | |
* There is an alternative to regex -- using DOMDocument -- but mind, the output might be broken if there are errors in $html input | |
$dom = new DOMDocument; | |
$dom->loadHTML($html); | |
foreach ($dom->getElementsByTagName('script') as $tag) { | |
if (strpos($tag->nodeValue, "var ic=w.Intercom") !== false) { | |
$tag->setAttribute('defer', ''); | |
$tag->removeAttribute('data-cfasync'); | |
$tag->nodeValue = str_replace("function l(){", "function l(){ setTimeout(function () {", $tag->nodeValue); | |
$tag->nodeValue = str_replace('x.parentNode.insertBefore(s,x);', 'x.parentNode.insertBefore(s,x);}, 3000);', $tag->nodeValue); | |
} | |
} | |
$html = $dom->saveHtml(); | |
**/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment