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', 'meta' => array( 'class' => 'hidden advanced_ads_ad_health_warning', 'target' => '_blank' ) ) );*/ // check if AdSense loads Auto Ads ads // Hidden, will be shown using js. if( ! isset( $adsense_options['violation-warnings-disable'] ) ) { $nodes[] = array( 'type' => 2, 'data' => array( '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', 'meta' => array( 'class' => 'hidden', 'target' => '_blank' ) ) ); } // check if current user was identified as a bot. if( Advanced_Ads::get_instance()->is_bot() ) { $nodes[] = array( 'type' => 1, 'data' => array( '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', 'meta' => array( 'class' => 'advanced_ads_ad_health_warning', 'target' => '_blank' ) ) ); } // check if an ad blocker is enabled // Hidden, will be shown using js. $nodes[] = array( 'type' => 2, 'data' => array( 'parent' => 'advanced_ads_ad_health', 'id' => 'advanced_ads_ad_health_adblocker_enabled', 'title' => __( 'Ad blocker enabled', 'advanced-ads' ), 'meta' => array( 'class' => 'hidden advanced_ads_ad_health_warning', 'target' => '_blank' ) ) ); if ( $wp_the_query->is_singular() ) { if ( $this->has_the_content_placements() ) { $nodes[] = array( 'type' => 2, 'data' => array( 'parent' => 'advanced_ads_ad_health', 'id' => 'advanced_ads_ad_health_the_content_not_invoked', 'title' => sprintf( __( '%s 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', 'meta' => array( 'class' => 'hidden advanced_ads_ad_health_warning', 'target' => '_blank' ) ) ); } if ( ! empty( $post->ID ) ) { $ad_settings = get_post_meta( $post->ID, '_advads_ad_settings', true ); if ( ! empty( $ad_settings['disable_the_content'] ) ) { $nodes[] = array( 'type' => 1, 'data' => array( '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', 'meta' => array( 'class' => 'advanced_ads_ad_health_warning', 'target' => '_blank' ) ) ); } } else { $nodes[] = array( 'type' => 1, 'data' => array( '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', 'meta' => array( 'class' => 'advanced_ads_ad_health_warning', 'target' => '_blank' ) ) ); } } $disabled_reason = Advanced_Ads::get_instance()->disabled_reason; $disabled_id = Advanced_Ads::get_instance()->disabled_id; if ( 'page' === $disabled_reason && $disabled_id ) { $nodes[] = array( 'type' => 1, 'data' => array( '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', 'meta' => array( 'class' => 'advanced_ads_ad_health_warning', 'target' => '_blank', ), ), ); } if ( 'all' === $disabled_reason ) { $nodes[] = array( 'type' => 1, 'data' => array( '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' ), 'meta' => array( 'class' => 'advanced_ads_ad_health_warning', 'target' => '_blank' ) ) ); } if ( '404' === $disabled_reason ) { $nodes[] = array( 'type' => 1, 'data' => array( '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' ), 'meta' => array( 'class' => 'advanced_ads_ad_health_warning', 'target' => '_blank', ), ), ); } if ( 'archive' === $disabled_reason ) { $nodes[] = array( 'type' => 1, 'data' => array( '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' ), 'meta' => array( 'class' => 'advanced_ads_ad_health_warning', 'target' => '_blank' ) ) ); } $nodes[] = array( 'type' => 2, 'data' => array( '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' ), '' ) ), 'href' => ADVADS_URL . 'manual/ad-health/?utm_source=advanced-ads&utm_medium=link&utm_campaign=adhealth-https-ads#https-ads', 'meta' => array( 'class' => 'hidden advanced_ads_ad_health_warning advanced_ads_ad_health_has_http', 'target' => '_blank' ) ) ); $nodes[] = array( 'type' => 2, 'data' => array( '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' ), '' ), 'href' => ADVADS_URL . 'manual/ad-health/?utm_source=advanced-ads&utm_medium=link&utm_campaign=adhealth-visible-ad-in-header#header-ads', 'meta' => array( 'class' => 'hidden advanced_ads_ad_health_warning advanced_ads_ad_health_incorrect_head', 'target' => '_blank' ) ) ); // warn if an AdSense ad seems to be hidden if( ! isset( $adsense_options['violation-warnings-disable'] ) ) { $nodes[] = array( 'type' => 2, 'data' => array( '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' ), '' ) ), 'href' => ADVADS_URL . 'manual/ad-health/?utm_source=advanced-ads&utm_medium=link&utm_campaign=adhealth-frontend-adsense-hidden#adsense-hidden', 'meta' => array( 'class' => 'hidden advanced_ads_ad_health_warning advanced_ads_ad_health_hidden_adsense', 'target' => '_blank' ) ) ); } $nodes[] = array( 'type' => 2, 'data' => array( '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' ), '' ), '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', 'meta' => array( 'class' => 'hidden advanced_ads_ad_health_warning advanced_ads_ad_health_floated_responsive_adsense', 'target' => '_blank' ) ) ); // warn if consent was not given $privacy = Advanced_Ads_Privacy::get_instance(); if ( 'not_needed' !== $privacy->get_state() ) { $nodes[] = array( 'type' => 2, 'data' => array( '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' ), 'meta' => array( 'class' => 'hidden advanced_ads_ad_health_warning advanced_ads_ad_health_consent_missing', 'target' => '_blank' ) ) ); } $privacy_options = $privacy->options(); if ( ( empty( $privacy_options['enabled'] ) || $privacy_options['consent-method'] !== 'iab_tcf_20' ) ) { $nodes[] = array( 'type' => 2, 'data' => array( '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' ), 'meta' => array( 'class' => 'hidden advanced_ads_ad_health_warning advanced_ads_ad_health_privacy_disabled', 'target' => '_blank', ), ), ); } $nodes[] = array( 'type' => 3, 'data' => array( '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' ) ), 'meta' => array( 'class' => 'hidden advanced_ads_ad_health_gam_debug_link', ) ) ); // link to highlight ads and jump from one ad to the next. $nodes[] = array( 'type' => 3, 'amp' => false, 'data' => array( 'parent' => 'advanced_ads_ad_health', 'id' => 'advanced_ads_ad_health_highlight_ads', 'title' => __( 'highlight ads', 'advanced-ads' ), 'meta' => array( 'class' => 'advanced_ads_ad_health_highlight_ads', ), ) ); /** * Add new node. * * @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, array( $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. } else { $warnings = $this->count_visible_warnings( $nodes, array( 1 ) ); } $issues = $warnings; $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_classes = array( '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 ); } global $post; 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 ) ) { $classes = array(); } if ( ! is_array( $aa_classes ) ) { $aa_classes = array(); } 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 = array() ) { $warnings = 0; foreach ( $nodes as $node ) { if ( ! isset( $node['type'] ) || ! isset( $node['data'] ) ) { continue; } if ( in_array( $node['type'], $types ) ) { $warnings++; } } return $warnings; } /** * Add header nodes. * * @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 ) { $wp_admin_bar->add_node( array( 'id' => 'advanced_ads_ad_health', 'title' => __( 'Ad Health', 'advanced-ads' ) . ' ' . $issues . '', 'parent' => false, 'href' => admin_url( 'admin.php?page=advanced-ads' ), 'meta' => array( 'class' => $issues ? 'advads-adminbar-is-warnings': '', ), ) ); // show that there are backend notices if ( $notices ) { $wp_admin_bar->add_node( array( 'parent' => 'advanced_ads_ad_health', 'id' => 'advanced_ads_ad_health_more', 'title' => sprintf(__( 'Show %d more notifications', 'advanced-ads' ), absint( $notices ) ), 'href' => admin_url( 'admin.php?page=advanced-ads' ), ) ); } } /** * Add footer nodes. * * @param obj $wp_admin_bar WP_Admin_Bar object. * @param int $issues Number of all issues. */ private function add_footer_nodes( $wp_admin_bar, $issues ) { if ( ! $issues ) { $wp_admin_bar->add_node( array( 'parent' => 'advanced_ads_ad_health', 'id' => 'advanced_ads_ad_health_fine', 'title' => __( 'Everything is fine', 'advanced-ads' ), 'href' => false, 'meta' => array( 'target' => '_blank', ) ) ); } $wp_admin_bar->add_node( array( 'parent' => 'advanced_ads_ad_health', 'id' => 'advanced_ads_ad_health_support', 'title' => __( 'Get help', 'advanced-ads' ), 'href' => Advanced_Ads_Plugin::support_url( '#utm_source=advanced-ads&utm_medium=link&utm_campaign=health-support' ), 'meta' => array( 'target' => '_blank', ) ) ); } /** * Filter out nodes intended to AMP pages only. * * @param array $nodes Nodes to add. * @return array $nodes Nodes to add. */ private function filter_nodes( $nodes ) { return $nodes; } /** * Sort nodes. */ function sort_nodes( $a, $b ) { if ( ! isset( $a['type'] ) || ! isset( $b['type'] ) ) { return 0; } if ( $a['type'] == $b['type'] ) { return 0; } return ( $a['type'] < $b['type'] ) ? -1 : 1; } /** * Set variable to 'true' when 'the_content' filter is invoked. * * @param string $content * @return string $content */ public function set_did_the_content( $content ) { if ( ! $this->did_the_content ) { $this->did_the_content = true; } if ( Advanced_Ads::get_instance()->has_many_the_content() ) { $this->has_many_the_content = true; } return $content; } /** * Check conditions and display warning. * Conditions: * AdBlocker enabled, * jQuery is included in header * AdSense Quick Start ads are running */ public function footer_checks() { ob_start(); ?> get_options(); ob_start(); ?> args['frontend-check'] ) ) { return $content; } if ( advads_is_amp() ) { return $content; } if ( Advanced_Ads_Ad_Debug::is_https_and_http( $ad ) ) { ob_start(); ?> get_options(); if ( 'adsense' === $ad->type && ! empty( $ad->args['cache_busting_elementid'] ) && ! isset( $adsense_options['violation-warnings-disable'] ) ) { ob_start(); ?> is_head_placement ) { return true; } // strip linebreaks, because, a line break after a comment is identified as a text node. $content = preg_replace( "/\r|\n/", "", $content ); if ( ! $dom = self::get_ad_dom( $content ) ) { return true; } $body = $dom->getElementsByTagName( 'body' )->item( 0 ); $count = $body->childNodes->length; for ( $i = 0; $i < $count; $i++ ) { $node = $body->childNodes->item( $i ); if ( XML_TEXT_NODE === $node->nodeType ) { return false; } if ( XML_ELEMENT_NODE === $node->nodeType && ! in_array( $node->nodeName, array( 'meta', 'link', 'title', 'style', 'script', 'noscript', 'base' ) ) ) { return false; } } return true; } /** * Convert ad content to a DOMDocument. * * @param string $content * @return DOMDocument|false */ private static function get_ad_dom( $content ) { if ( ! extension_loaded( 'dom' ) ) { return false; } $libxml_previous_state = libxml_use_internal_errors( true ); $dom = new DOMDocument(); $result = $dom->loadHTML( '
' . $content . '' ); libxml_clear_errors(); libxml_use_internal_errors( $libxml_previous_state ); if ( ! $result ) { return false; } return $dom; } /** * Check if at least one placement uses `the_content`. * * @return bool True/False. */ private function has_the_content_placements() { $placements = Advanced_Ads::get_ad_placements_array(); $placement_types = Advanced_Ads_Placements::get_placement_types(); // Find a placement that depends on 'the_content' filter. foreach ( $placements as $placement ) { if ( isset ( $placement['type'] ) && ! empty( $placement_types[ $placement['type'] ]['options']['uses_the_content'] ) ) { return true; } } return false; } }