: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
use AdvancedAds\Assets_Registry;
use AdvancedAds\Utilities\WordPress;
* Class Advanced_Ads_Frontend_Checks
* Handle Ad Health and other notifications and checks in the frontend.
class Advanced_Ads_Frontend_Checks {
* True if 'the_content' was invoked, false otherwise.
private $did_the_content = false;
private $has_many_the_content = false;
public function __construct() {
// Wait until other plugins (for example Elementor) have disabled admin bar using `show_admin_bar` filter.
add_action( 'template_redirect', [ $this, 'init' ], 11 );
add_filter( 'advanced-ads-ad-output', [ $this, 'after_ad_output' ], 10, 2 );
&& is_admin_bar_showing()
&& WordPress::user_can( 'advanced_ads_edit_ads' )
&& Advanced_Ads_Ad_Health_Notices::notices_enabled()
add_action( 'admin_bar_menu', [ $this, 'add_admin_bar_menu' ], 1000 );
add_filter( 'the_content', [ $this, 'set_did_the_content' ] );
add_action( 'wp_footer', [ $this, 'footer_checks' ], -101 );
add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
add_filter( 'advanced-ads-ad-select-args', [ $this, 'ad_select_args_callback' ] );
add_filter( 'advanced-ads-ad-output', [ $this, 'after_ad_output' ], 10, 2 );
if ( Advanced_Ads_Ad_Health_Notices::notices_enabled() ) {
add_action( 'body_class', [ $this, 'body_class' ] );
if( $this->has_adblocker_placements() ) {
if ( ! Assets_Registry::script_is('find-adblocker', 'enqueued') ) {
Assets_Registry::enqueue_script('find-adblocker');
* Notify ads loaded with AJAX.
* @param array $args ad arguments.
public function ad_select_args_callback( $args ) {
$args['frontend-check'] = true;
* needs to add ajaxurl in case no other plugin is doing that
public function enqueue_scripts() {
// we don’t have our own script, so we attach this information to jquery.
wp_localize_script( 'jquery', 'advads_frontend_checks', [ 'ajax_url' => admin_url( 'admin-ajax.php' ) ] );
* List current ad situation on the page in the admin-bar.
* @param object $wp_admin_bar WP_Admin_Bar.
public function add_admin_bar_menu( $wp_admin_bar ) {
global $wp_the_query, $post, $wp_scripts;
$options = Advanced_Ads_Plugin::get_instance()->options();
// load AdSense related options.
$adsense_options = Advanced_Ads_AdSense_Data::get_instance()->get_options();
// check if jQuery is loaded in the header
// Hidden, will be shown using js.
// message removed after we fixed all issues we know of.
$wp_admin_bar->add_node( array(
'parent' => 'advanced_ads_ad_health',
'id' => 'advanced_ads_ad_health_jquery',
'title' => __( 'jQuery not in header', 'advanced-ads' ),
'href' => ADVADS_URL . 'manual/common-issues#frontend-issues-javascript',
'class' => 'hidden advanced_ads_ad_health_warning',
// check if AdSense loads Auto Ads ads
// Hidden, will be shown using js.
if ( ! isset( $adsense_options['violation-warnings-disable'] ) ) {
'parent' => 'advanced_ads_ad_health',
'id' => 'advanced_ads_autoads_displayed',
'title' => __( 'Random AdSense ads', 'advanced-ads' ),
'href' => ADVADS_URL . 'adsense-in-random-positions-auto-ads/?utm_source=advanced-ads&utm_medium=link&utm_campaign=frontend-autoads-ads',
// check if current user was identified as a bot.
if ( Advanced_Ads::get_instance()->is_bot() ) {
$nodes[] = [ 'type' => 1, 'data' => [
'parent' => 'advanced_ads_ad_health',
'id' => 'advanced_ads_user_is_bot',
'title' => __( 'You look like a bot', 'advanced-ads' ),
'href' => ADVADS_URL . 'manual/ad-health/#look-like-bot',
'class' => 'advanced_ads_ad_health_warning',
// check if an ad blocker is enabled
// Hidden, will be shown using js.
$nodes[] = [ 'type' => 2, 'data' => [
'parent' => 'advanced_ads_ad_health',
'id' => 'advanced_ads_ad_health_adblocker_enabled',
'title' => __( 'Ad blocker enabled', 'advanced-ads' ),
'class' => 'hidden advanced_ads_ad_health_warning',
if ( $wp_the_query->is_singular() ) {
if ( $this->has_the_content_placements() ) {
$nodes[] = [ 'type' => 2, 'data' => [
'parent' => 'advanced_ads_ad_health',
'id' => 'advanced_ads_ad_health_the_content_not_invoked',
'title' => sprintf( __( '<em>%s</em> filter does not exist', 'advanced-ads' ), 'the_content' ),
'href' => ADVADS_URL . 'manual/ads-not-showing-up/?utm_source=advanced-ads&utm_medium=link&utm_campaign=adhealth-content-filter-missing#the_content-filter-missing',
'class' => 'hidden advanced_ads_ad_health_warning',
if ( ! empty( $post->ID ) ) {
$ad_settings = get_post_meta( $post->ID, '_advads_ad_settings', true );
if ( ! empty( $ad_settings['disable_the_content'] ) ) {
$nodes[] = [ 'type' => 1, 'data' => [
'parent' => 'advanced_ads_ad_health',
'id' => 'advanced_ads_ad_health_disabled_in_content',
'title' => __( 'Ads are disabled in the content of this page', 'advanced-ads' ),
'href' => get_edit_post_link( $post->ID ) . '#advads-ad-settings',
'class' => 'advanced_ads_ad_health_warning',
$nodes[] = [ 'type' => 1, 'data' => [
'parent' => 'advanced_ads_ad_health',
'id' => 'advanced_ads_ad_health_post_zero',
'title' => __( 'the current post ID is 0 ', 'advanced-ads' ),
'href' => ADVADS_URL . 'manual/ad-health/#post-id-0',
'class' => 'advanced_ads_ad_health_warning',
$disabled_reason = Advanced_Ads::get_instance()->disabled_reason;
$disabled_id = Advanced_Ads::get_instance()->disabled_id;
if ( 'page' === $disabled_reason && $disabled_id ) {
'parent' => 'advanced_ads_ad_health',
'id' => 'advanced_ads_ad_health_disabled_on_page',
'title' => __( 'Ads are disabled on this page', 'advanced-ads' ),
'href' => get_edit_post_link( $disabled_id ) . '#advads-ad-settings',
'class' => 'advanced_ads_ad_health_warning',
if ( 'all' === $disabled_reason ) {
$nodes[] = [ 'type' => 1, 'data' => [
'parent' => 'advanced_ads_ad_health',
'id' => 'advanced_ads_ad_health_no_all',
'title' => __( 'Ads are disabled on all pages', 'advanced-ads' ),
'href' => admin_url( 'admin.php?page=advanced-ads-settings' ),
'class' => 'advanced_ads_ad_health_warning',
if ( '404' === $disabled_reason ) {
'parent' => 'advanced_ads_ad_health',
'id' => 'advanced_ads_ad_health_no_404',
'title' => __( 'Ads are disabled on 404 pages', 'advanced-ads' ),
'href' => admin_url( 'admin.php?page=advanced-ads-settings' ),
'class' => 'advanced_ads_ad_health_warning',
if ( 'archive' === $disabled_reason ) {
$nodes[] = [ 'type' => 1, 'data' => [
'parent' => 'advanced_ads_ad_health',
'id' => 'advanced_ads_ad_health_no_archive',
'title' => __( 'Ads are disabled on non singular pages', 'advanced-ads' ),
'href' => admin_url( 'admin.php?page=advanced-ads-settings' ),
'class' => 'advanced_ads_ad_health_warning',
$nodes[] = [ 'type' => 2, 'data' => [
'parent' => 'advanced_ads_ad_health',
'id' => 'advanced_ads_ad_health_has_http',
'title' => sprintf( '%s %s',
__( 'Your website is using HTTPS, but the ad code contains HTTP and might not work.', 'advanced-ads' ),
sprintf( __( 'Ad IDs: %s', 'advanced-ads' ), '<i></i>' )
'href' => ADVADS_URL . 'manual/ad-health/?utm_source=advanced-ads&utm_medium=link&utm_campaign=adhealth-https-ads#https-ads',
'class' => 'hidden advanced_ads_ad_health_warning advanced_ads_ad_health_has_http',
$nodes[] = [ 'type' => 2, 'data' => [
'parent' => 'advanced_ads_ad_health',
'id' => 'advanced_ads_ad_health_incorrect_head',
'title' => sprintf( __( 'Visible ads should not use the Header placement: %s', 'advanced-ads' ), '<i></i>' ),
'href' => ADVADS_URL . 'manual/ad-health/?utm_source=advanced-ads&utm_medium=link&utm_campaign=adhealth-visible-ad-in-header#header-ads',
'class' => 'hidden advanced_ads_ad_health_warning advanced_ads_ad_health_incorrect_head',
// warn if an AdSense ad seems to be hidden.
if ( ! isset( $adsense_options['violation-warnings-disable'] ) ) {
'parent' => 'advanced_ads_ad_health',
'id' => 'advanced_ads_ad_health_hidden_adsense',
'title' => sprintf( '%s: %s. %s',
__( 'AdSense violation', 'advanced-ads' ),
__( 'Ad is hidden', 'advanced-ads' ),
sprintf( __( 'IDs: %s', 'advanced-ads' ), '<i></i>' )
'href' => ADVADS_URL . 'manual/ad-health/?utm_source=advanced-ads&utm_medium=link&utm_campaign=adhealth-frontend-adsense-hidden#adsense-hidden',
'class' => 'hidden advanced_ads_ad_health_warning advanced_ads_ad_health_hidden_adsense',
'parent' => 'advanced_ads_ad_health',
'id' => 'advanced_ads_ad_health_floated_responsive_adsense',
'title' => sprintf( __( 'The following responsive AdSense ads are not showing up: %s', 'advanced-ads' ), '<i></i>' ),
'href' => ADVADS_URL . 'manual/ad-health/?utm_source=advanced-ads&utm_medium=link&utm_campaign=adhealth-adsense-responsive-not-showing#The_following_responsive_AdSense_ads_arenot_showing_up',
'class' => 'hidden advanced_ads_ad_health_warning advanced_ads_ad_health_floated_responsive_adsense',
// warn if consent was not given.
$privacy = Advanced_Ads_Privacy::get_instance();
if ( 'not_needed' !== $privacy->get_state() ) {
'parent' => 'advanced_ads_ad_health',
'id' => 'advanced_ads_ad_health_consent_missing',
'title' => __( 'Consent not given', 'advanced-ads' ),
'href' => admin_url( 'admin.php?page=advanced-ads-settings#top#privacy' ),
'class' => 'hidden advanced_ads_ad_health_warning advanced_ads_ad_health_consent_missing',
$privacy_options = $privacy->options();
if ( ( empty( $privacy_options['enabled'] ) || $privacy_options['consent-method'] !== 'iab_tcf_20' ) ) {
'parent' => 'advanced_ads_ad_health',
'id' => 'advanced_ads_ad_health_privacy_disabled',
'title' => __( 'Enable TCF integration', 'advanced-ads' ),
'href' => admin_url( 'admin.php?page=advanced-ads-settings#top#privacy' ),
'class' => 'hidden advanced_ads_ad_health_warning advanced_ads_ad_health_privacy_disabled',
'parent' => 'advanced_ads_ad_health',
'id' => 'advanced_ads_ad_health_gam_debug',
'title' => __( 'Debug Google Ad Manager', 'advanced-ads' ),
'href' => esc_url( add_query_arg( 'google_force_console', '1' ) ),
'class' => 'hidden advanced_ads_ad_health_gam_debug_link',
// link to highlight ads and jump from one ad to the next.
'parent' => 'advanced_ads_ad_health',
'id' => 'advanced_ads_ad_health_highlight_ads',
'<span class="link">%s</span> %s',
__( 'highlight ads', 'advanced-ads' ),
<i class = "dashicons dashicons-arrow-up-alt previous"></i>
<i class = "dashicons dashicons-arrow-down-alt next"></i>
'class' => 'advanced_ads_ad_health_highlight_ads',
* @param array $node An array that contains:
* 'type' => 1 - warning, 2 - hidden warning that will be shown using JS, 3 - info message
* 'data': @see WP_Admin_Bar->add_node
* @param object $wp_admin_bar
$nodes = apply_filters( 'advanced-ads-ad-health-nodes', $nodes );
usort( $nodes, [ $this, 'sort_nodes' ] );
// load number of already detected notices.
$notices = Advanced_Ads_Ad_Health_Notices::get_number_of_notices();
if ( ! advads_is_amp() ) {
$warnings = 0; // Will be updated using JS.
$warnings = $this->count_visible_warnings( $nodes, [ 1 ] );
$this->add_header_nodes( $wp_admin_bar, $issues, $notices );
foreach ( $nodes as $node ) {
if ( isset( $node['data'] ) ) {
$wp_admin_bar->add_node( $node['data'] );
$this->add_footer_nodes( $wp_admin_bar, $issues );
* Add classes to the `body` tag.
* @param string[] $classes Array of existing class names.
* @return string[] $classes Array of existing and new class names.
public function body_class( $classes ) {
'aa-prefix-' . Advanced_Ads_Plugin::get_instance()->get_frontend_prefix(),
$disabled_reason = Advanced_Ads::get_instance()->disabled_reason;
if ( $disabled_reason ) {
$aa_classes[] = 'aa-disabled-' . esc_attr( $disabled_reason );
if ( ! empty( $post->ID ) ) {
$ad_settings = get_post_meta( $post->ID, '_advads_ad_settings', true );
if ( ! empty( $ad_settings['disable_the_content'] ) ) {
$aa_classes[] = 'aa-disabled-content';
// hide-ads-from-bots option is enabled.
$options = Advanced_Ads_Plugin::get_instance()->options();
if ( ! empty( $options['block-bots'] ) ) {
$aa_classes[] = 'aa-disabled-bots';
$aa_classes = apply_filters( 'advanced-ads-body-classes', $aa_classes );
if ( ! is_array( $classes ) ) {
if ( ! is_array( $aa_classes ) ) {
return array_merge( $classes, $aa_classes );
* Count visible notices and warnings.
* @param array $nodes Nodes to add.
* @param array $types Warning types.
private function count_visible_warnings( $nodes, $types = [] ) {
foreach ( $nodes as $node ) {
if ( ! isset( $node['type'] ) || ! isset( $node['data'] ) ) { continue; }
if ( in_array( $node['type'], $types ) ) {
* @param object $wp_admin_bar WP_Admin_Bar object.
* @param int $issues Number of all issues.
* @param int $notices Number of notices.
private function add_header_nodes( $wp_admin_bar, $issues, $notices ) {
'id' => 'advanced_ads_ad_health',
'title' => __( 'Ad Health', 'advanced-ads' ) . ' <span class="advanced-ads-issue-counter">' . $issues . '</span>',