PluginProbe ʕ •ᴥ•ʔ
Advanced Ads – Ad Manager & AdSense / 1.39.2
Advanced Ads – Ad Manager & AdSense v1.39.2
2.0.23 2.0.22 2.0.21 1.38.0 1.39.0 1.39.1 1.39.2 1.39.3 1.39.4 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.40.0 1.40.1 1.40.2 1.41.0 1.42.0 1.42.1 1.42.2 1.43.0 1.44.0 1.44.1 1.45.0 1.45.1 1.46.0 1.47.0 1.47.1 1.47.2 1.47.3 1.47.4 1.47.5 1.48.0 1.48.1 1.49.0 1.5.0 1.5.0.1 1.5.1 1.5.2 1.5.2.1 1.5.4 1.5.4.1 1.5.5 1.50.0 1.51.0 1.51.1 1.51.2 1.51.3 1.52.0 1.52.1 1.52.2 1.52.3 1.52.4 1.53.0 1.53.1 1.53.2 1.54.0 1.54.1 1.55.0 1.56.0 1.56.1 1.56.2 1.56.3 1.56.4 1.6 1.6.1 1.6.10 1.6.10.1 1.6.10.2 1.6.11 1.6.11.1 1.6.12 1.6.13 1.6.14 1.6.15 1.6.16 1.6.17 1.6.17.1 1.6.17.2 1.6.2 1.6.2.1 1.6.3 1.6.4 1.6.4.1 1.6.5 1.6.6 1.6.6.1 1.6.7 1.6.7.1 1.6.8 1.6.8.1 1.6.8.2 1.6.8.3 1.6.9 1.6.9.1 1.6.9.2 1.6.9.3 1.6.9.4 1.7 1.7.0.1 1.7.0.2 1.7.0.3 1.7.1 1.7.1.1 1.7.1.2 1.7.1.3 1.7.1.4 1.7.1.5 1.7.10 trunk 1.7.11 1.0.1 1.7.12 1.0.2 1.7.13 1.0.3 1.7.14 1.1.0 1.7.15 1.1.1 1.7.16 1.1.2 1.7.17 1.1.3 1.7.18 1.10 1.7.19 1.10.1 1.7.2 1.10.10 1.7.2.1 1.10.11 1.7.20 1.10.12 1.7.21 1.10.2 1.7.22 1.10.3 1.7.23 1.10.4 1.7.24 1.10.5 1.7.25 1.10.6 1.7.3 1.10.7 1.7.4 1.10.8 1.7.4.1 1.10.9 1.7.4.2 1.11 1.7.4.3 1.11.1 1.7.4.4 1.11.2 1.7.4.5 1.12 1.7.5 1.13 1.7.5.1 1.13.1 1.7.6 1.13.2 1.7.7 1.13.3 1.7.8 1.13.4 1.7.9 1.13.5 1.7.9.1 1.13.6 1.7.9.2 1.13.7 1.7.9.3 1.13.8 1.8 1.14 1.8.1 1.14.1 1.8.10 1.14.10 1.8.11 1.14.11 1.8.12 1.14.2 1.8.13 1.14.3 1.8.14 1.14.4 1.8.15 1.14.5 1.8.16 1.14.6 1.8.17 1.14.7 1.8.18 1.14.8 1.8.19 1.14.9 1.8.2 1.15 1.8.20 1.16 1.8.21 1.16.1 1.8.22 1.17 1.8.23 1.17.1 1.8.24 1.17.10 1.8.25 1.17.10-rc.1 1.8.26 1.17.11 1.8.27 1.17.12 1.8.28 1.17.12-rc.1 1.8.29 1.17.2 1.8.3 1.17.3 1.8.30 1.17.4 1.8.4 1.17.5 1.8.5 1.17.6 1.8.6 1.17.7 1.8.7 1.17.8 1.8.8 1.17.9 1.8.9 1.17.9-beta.1 1.9 1.18.0 2.0.0 1.19.0 2.0.1 1.19.1 2.0.10 1.2 2.0.11 1.2.1 2.0.12 1.2.2 2.0.13 1.2.3 2.0.14 1.2.4 2.0.15 1.2.5 2.0.16 1.2.6 2.0.17 1.2.7 2.0.18 1.20.0 2.0.19 1.20.0-rc.1 2.0.2 1.20.0-rc.2 2.0.20 1.20.1 2.0.3 1.20.2 2.0.4 1.20.3 2.0.5 1.21.0 2.0.6 1.21.1 2.0.7 1.22.0 2.0.8 1.22.1 2.0.9 1.22.2 1.23.0 1.23.1 1.23.2 1.24.0 1.24.1 1.24.2 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.29.0 1.29.1 1.3 1.3.1 1.3.10 1.3.11 1.3.12 1.3.13 1.3.14 1.3.15 1.3.16 1.3.17 1.3.18 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.30.0 1.30.1 1.30.2 1.30.2-rc.1 1.30.3 1.30.4 1.30.4-rc.1 1.30.5 1.31.0 1.31.1 1.32.0 1.32.0-rc.1 1.33.0 1.33.1 1.33.2 1.34.0 1.35.0 1.35.1 1.36.0 1.36.1 1.36.2 1.36.3 1.37.0 1.37.1 1.37.2
advanced-ads / classes / frontend_checks.php
advanced-ads / classes Last commit date
Advanced_Ads_Modal.php 3 years ago EDD_SL_Plugin_Updater.php 4 years ago ad-ajax.php 3 years ago ad-debug.php 3 years ago ad-expiration.php 3 years ago ad-health-notices.php 3 years ago ad-model.php 3 years ago ad-select.php 3 years ago ad.php 3 years ago ad_ajax_callbacks.php 3 years ago ad_group.php 3 years ago ad_placements.php 3 years ago ad_type_abstract.php 3 years ago ad_type_content.php 3 years ago ad_type_dummy.php 3 years ago ad_type_group.php 3 years ago ad_type_image.php 3 years ago ad_type_plain.php 3 years ago checks.php 3 years ago compatibility.php 3 years ago display-conditions.php 3 years ago filesystem.php 3 years ago frontend-notices.php 3 years ago frontend_checks.php 3 years ago in-content-injector.php 3 years ago inline-css.php 3 years ago plugin.php 3 years ago upgrades.php 6 years ago utils.php 3 years ago visitor-conditions.php 3 years ago widget.php 3 years ago
frontend_checks.php
1139 lines
1 <?php
2
3 /**
4 * Class Advanced_Ads_Frontend_Checks
5 *
6 * Handle Ad Health and other notifications and checks in the frontend.
7 */
8 class Advanced_Ads_Frontend_Checks {
9 /**
10 * True if 'the_content' was invoked, false otherwise.
11 *
12 * @var bool
13 */
14 private $did_the_content = false;
15 private $has_many_the_content = false;
16
17 /**
18 * Constructor.
19 */
20 public function __construct() {
21 // Wait until other plugins (for example Elementor) have disabled admin bar using `show_admin_bar` filter.
22 add_action( 'template_redirect', [ $this, 'init' ], 11 );
23
24 if ( wp_doing_ajax() ) {
25 add_filter( 'advanced-ads-ad-output', [ $this, 'after_ad_output' ], 10, 2 );
26 }
27 }
28
29 /**
30 * Ad Health init.
31 */
32 public function init() {
33 if ( ! is_admin()
34 && is_admin_bar_showing()
35 && current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_edit_ads' ) )
36 && Advanced_Ads_Ad_Health_Notices::notices_enabled()
37 ) {
38 add_action( 'admin_bar_menu', [ $this, 'add_admin_bar_menu' ], 1000 );
39 add_filter( 'the_content', [ $this, 'set_did_the_content' ] );
40 add_action( 'wp_footer', [ $this, 'footer_checks' ], -101 );
41 add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
42 add_filter( 'advanced-ads-ad-select-args', [ $this, 'ad_select_args_callback' ] );
43 add_filter( 'advanced-ads-ad-output', [ $this, 'after_ad_output' ], 10, 2 );
44 }
45
46 if ( Advanced_Ads_Ad_Health_Notices::notices_enabled() ) {
47 add_action( 'body_class', [ $this, 'body_class' ] );
48 }
49 }
50
51 /**
52 * Notify ads loaded with AJAX.
53 *
54 * @param array $args ad arguments.
55 * @return array $args
56 */
57 public function ad_select_args_callback( $args ) {
58 $args['frontend-check'] = true;
59 return $args;
60 }
61
62 /**
63 * Enqueue scripts
64 * needs to add ajaxurl in case no other plugin is doing that
65 */
66 public function enqueue_scripts() {
67 if ( advads_is_amp() ) {
68 return;
69 }
70
71 // we don’t have our own script, so we attach this information to jquery
72 wp_localize_script( 'jquery', 'advads_frontend_checks',
73 [ 'ajax_url' => admin_url( 'admin-ajax.php' ) ] );
74 }
75
76 /**
77 * List current ad situation on the page in the admin-bar.
78 *
79 * @param object $wp_admin_bar WP_Admin_Bar.
80 */
81 public function add_admin_bar_menu( $wp_admin_bar ) {
82 global $wp_the_query, $post, $wp_scripts;
83
84 $options = Advanced_Ads_Plugin::get_instance()->options();
85
86 // load AdSense related options.
87 $adsense_options = Advanced_Ads_AdSense_Data::get_instance()->get_options();
88
89 // check if jQuery is loaded in the header
90 // Hidden, will be shown using js.
91 // message removed after we fixed all issues we know of.
92 /*$wp_admin_bar->add_node( array(
93 'parent' => 'advanced_ads_ad_health',
94 'id' => 'advanced_ads_ad_health_jquery',
95 'title' => __( 'jQuery not in header', 'advanced-ads' ),
96 'href' => ADVADS_URL . 'manual/common-issues#frontend-issues-javascript',
97 'meta' => array(
98 'class' => 'hidden advanced_ads_ad_health_warning',
99 'target' => '_blank'
100 )
101 ) );*/
102
103 // check if AdSense loads Auto Ads ads
104 // Hidden, will be shown using js.
105 if( ! isset( $adsense_options['violation-warnings-disable'] ) ) {
106 $nodes[] = [ 'type' => 2, 'data' => [
107 'parent' => 'advanced_ads_ad_health',
108 'id' => 'advanced_ads_autoads_displayed',
109 'title' => __( 'Random AdSense ads', 'advanced-ads' ),
110 'href' => ADVADS_URL . 'adsense-in-random-positions-auto-ads/?utm_source=advanced-ads&utm_medium=link&utm_campaign=frontend-autoads-ads',
111 'meta' => [
112 'class' => 'hidden',
113 'target' => '_blank'
114 ]
115 ] ];
116 }
117
118 // check if current user was identified as a bot.
119 if( Advanced_Ads::get_instance()->is_bot() ) {
120 $nodes[] = [ 'type' => 1, 'data' => [
121 'parent' => 'advanced_ads_ad_health',
122 'id' => 'advanced_ads_user_is_bot',
123 'title' => __( 'You look like a bot', 'advanced-ads' ),
124 'href' => ADVADS_URL . 'manual/ad-health/#look-like-bot',
125 'meta' => [
126 'class' => 'advanced_ads_ad_health_warning',
127 'target' => '_blank'
128 ]
129 ] ];
130 }
131
132 // check if an ad blocker is enabled
133 // Hidden, will be shown using js.
134 $nodes[] = [ 'type' => 2, 'data' => [
135 'parent' => 'advanced_ads_ad_health',
136 'id' => 'advanced_ads_ad_health_adblocker_enabled',
137 'title' => __( 'Ad blocker enabled', 'advanced-ads' ),
138 'meta' => [
139 'class' => 'hidden advanced_ads_ad_health_warning',
140 'target' => '_blank'
141 ]
142 ] ];
143
144 if ( $wp_the_query->is_singular() ) {
145 if ( $this->has_the_content_placements() ) {
146 $nodes[] = [ 'type' => 2, 'data' => [
147 'parent' => 'advanced_ads_ad_health',
148 'id' => 'advanced_ads_ad_health_the_content_not_invoked',
149 'title' => sprintf( __( '<em>%s</em> filter does not exist', 'advanced-ads' ), 'the_content' ),
150 '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',
151 'meta' => [
152 'class' => 'hidden advanced_ads_ad_health_warning',
153 'target' => '_blank'
154 ]
155 ] ];
156 }
157
158 if ( ! empty( $post->ID ) ) {
159 $ad_settings = get_post_meta( $post->ID, '_advads_ad_settings', true );
160
161 if ( ! empty( $ad_settings['disable_the_content'] ) ) {
162 $nodes[] = [ 'type' => 1, 'data' => [
163 'parent' => 'advanced_ads_ad_health',
164 'id' => 'advanced_ads_ad_health_disabled_in_content',
165 'title' => __( 'Ads are disabled in the content of this page', 'advanced-ads' ),
166 'href' => get_edit_post_link( $post->ID ) . '#advads-ad-settings',
167 'meta' => [
168 'class' => 'advanced_ads_ad_health_warning',
169 'target' => '_blank'
170 ]
171 ] ];
172 }
173 } else {
174 $nodes[] = [ 'type' => 1, 'data' => [
175 'parent' => 'advanced_ads_ad_health',
176 'id' => 'advanced_ads_ad_health_post_zero',
177 'title' => __( 'the current post ID is 0 ', 'advanced-ads' ),
178 'href' => ADVADS_URL . 'manual/ad-health/#post-id-0',
179 'meta' => [
180 'class' => 'advanced_ads_ad_health_warning',
181 'target' => '_blank'
182 ]
183 ] ];
184 }
185 }
186
187 $disabled_reason = Advanced_Ads::get_instance()->disabled_reason;
188 $disabled_id = Advanced_Ads::get_instance()->disabled_id;
189
190 if ( 'page' === $disabled_reason && $disabled_id ) {
191 $nodes[] = [
192 'type' => 1,
193 'data' => [
194 'parent' => 'advanced_ads_ad_health',
195 'id' => 'advanced_ads_ad_health_disabled_on_page',
196 'title' => __( 'Ads are disabled on this page', 'advanced-ads' ),
197 'href' => get_edit_post_link( $disabled_id ) . '#advads-ad-settings',
198 'meta' => [
199 'class' => 'advanced_ads_ad_health_warning',
200 'target' => '_blank',
201 ],
202 ],
203 ];
204 }
205
206 if ( 'all' === $disabled_reason ) {
207 $nodes[] = [ 'type' => 1, 'data' => [
208 'parent' => 'advanced_ads_ad_health',
209 'id' => 'advanced_ads_ad_health_no_all',
210 'title' => __( 'Ads are disabled on all pages', 'advanced-ads' ),
211 'href' => admin_url( 'admin.php?page=advanced-ads-settings' ),
212 'meta' => [
213 'class' => 'advanced_ads_ad_health_warning',
214 'target' => '_blank'
215 ]
216 ] ];
217 }
218
219 if ( '404' === $disabled_reason ) {
220 $nodes[] = [
221 'type' => 1,
222 'data' => [
223 'parent' => 'advanced_ads_ad_health',
224 'id' => 'advanced_ads_ad_health_no_404',
225 'title' => __( 'Ads are disabled on 404 pages', 'advanced-ads' ),
226 'href' => admin_url( 'admin.php?page=advanced-ads-settings' ),
227 'meta' => [
228 'class' => 'advanced_ads_ad_health_warning',
229 'target' => '_blank',
230 ],
231 ],
232 ];
233 }
234
235 if ( 'archive' === $disabled_reason ) {
236 $nodes[] = [ 'type' => 1, 'data' => [
237 'parent' => 'advanced_ads_ad_health',
238 'id' => 'advanced_ads_ad_health_no_archive',
239 'title' => __( 'Ads are disabled on non singular pages', 'advanced-ads' ),
240 'href' => admin_url( 'admin.php?page=advanced-ads-settings' ),
241 'meta' => [
242 'class' => 'advanced_ads_ad_health_warning',
243 'target' => '_blank'
244 ]
245 ] ];
246 }
247
248 $nodes[] = [ 'type' => 2, 'data' => [
249 'parent' => 'advanced_ads_ad_health',
250 'id' => 'advanced_ads_ad_health_has_http',
251 'title' => sprintf( '%s %s',
252 __( 'Your website is using HTTPS, but the ad code contains HTTP and might not work.', 'advanced-ads' ),
253 sprintf( __( 'Ad IDs: %s', 'advanced-ads' ), '<i></i>' )
254 ),
255 'href' => ADVADS_URL . 'manual/ad-health/?utm_source=advanced-ads&utm_medium=link&utm_campaign=adhealth-https-ads#https-ads',
256 'meta' => [
257 'class' => 'hidden advanced_ads_ad_health_warning advanced_ads_ad_health_has_http',
258 'target' => '_blank'
259 ]
260 ] ];
261
262 $nodes[] = [ 'type' => 2, 'data' => [
263 'parent' => 'advanced_ads_ad_health',
264 'id' => 'advanced_ads_ad_health_incorrect_head',
265 'title' => sprintf( __( 'Visible ads should not use the Header placement: %s', 'advanced-ads' ), '<i></i>' ),
266 'href' => ADVADS_URL . 'manual/ad-health/?utm_source=advanced-ads&utm_medium=link&utm_campaign=adhealth-visible-ad-in-header#header-ads',
267 'meta' => [
268 'class' => 'hidden advanced_ads_ad_health_warning advanced_ads_ad_health_incorrect_head',
269 'target' => '_blank'
270 ]
271 ] ];
272
273 // warn if an AdSense ad seems to be hidden
274 if( ! isset( $adsense_options['violation-warnings-disable'] ) ) {
275 $nodes[] = [ 'type' => 2, 'data' => [
276 'parent' => 'advanced_ads_ad_health',
277 'id' => 'advanced_ads_ad_health_hidden_adsense',
278 'title' => sprintf( '%s: %s. %s',
279 __( 'AdSense violation', 'advanced-ads' ),
280 __( 'Ad is hidden', 'advanced-ads' ),
281 sprintf( __( 'IDs: %s', 'advanced-ads' ), '<i></i>' )
282 ),
283 'href' => ADVADS_URL . 'manual/ad-health/?utm_source=advanced-ads&utm_medium=link&utm_campaign=adhealth-frontend-adsense-hidden#adsense-hidden',
284 'meta' => [
285 'class' => 'hidden advanced_ads_ad_health_warning advanced_ads_ad_health_hidden_adsense',
286 'target' => '_blank'
287 ]
288 ] ];
289 }
290
291 $nodes[] = [ 'type' => 2, 'data' => [
292 'parent' => 'advanced_ads_ad_health',
293 'id' => 'advanced_ads_ad_health_floated_responsive_adsense',
294 'title' => sprintf( __( 'The following responsive AdSense ads are not showing up: %s', 'advanced-ads' ), '<i></i>' ),
295 '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',
296 'meta' => [
297 'class' => 'hidden advanced_ads_ad_health_warning advanced_ads_ad_health_floated_responsive_adsense',
298 'target' => '_blank'
299 ]
300 ] ];
301
302 // warn if consent was not given
303 $privacy = Advanced_Ads_Privacy::get_instance();
304 if ( 'not_needed' !== $privacy->get_state() ) {
305 $nodes[] = [ 'type' => 2, 'data' => [
306 'parent' => 'advanced_ads_ad_health',
307 'id' => 'advanced_ads_ad_health_consent_missing',
308 'title' => __( 'Consent not given', 'advanced-ads' ),
309 'href' => admin_url( 'admin.php?page=advanced-ads-settings#top#privacy' ),
310 'meta' => [
311 'class' => 'hidden advanced_ads_ad_health_warning advanced_ads_ad_health_consent_missing',
312 'target' => '_blank'
313 ]
314 ] ];
315 }
316
317 $privacy_options = $privacy->options();
318 if ( ( empty( $privacy_options['enabled'] ) || $privacy_options['consent-method'] !== 'iab_tcf_20' ) ) {
319 $nodes[] = [
320 'type' => 2,
321 'data' => [
322 'parent' => 'advanced_ads_ad_health',
323 'id' => 'advanced_ads_ad_health_privacy_disabled',
324 'title' => __( 'Enable TCF integration', 'advanced-ads' ),
325 'href' => admin_url( 'admin.php?page=advanced-ads-settings#top#privacy' ),
326 'meta' => [
327 'class' => 'hidden advanced_ads_ad_health_warning advanced_ads_ad_health_privacy_disabled',
328 'target' => '_blank',
329 ],
330 ],
331 ];
332 }
333
334 $nodes[] = [ 'type' => 3, 'data' => [
335 'parent' => 'advanced_ads_ad_health',
336 'id' => 'advanced_ads_ad_health_gam_debug',
337 'title' => __( 'Debug Google Ad Manager', 'advanced-ads' ),
338 'href' => esc_url( add_query_arg( 'google_force_console', '1' ) ),
339 'meta' => [
340 'class' => 'hidden advanced_ads_ad_health_gam_debug_link',
341 ]
342 ] ];
343
344 // link to highlight ads and jump from one ad to the next.
345 $nodes[] = [ 'type' => 3, 'amp' => false, 'data' => [
346 'parent' => 'advanced_ads_ad_health',
347 'id' => 'advanced_ads_ad_health_highlight_ads',
348 'title' => __( 'highlight ads', 'advanced-ads' ),
349 'meta' => [
350 'class' => 'advanced_ads_ad_health_highlight_ads',
351 ],
352 ] ];
353
354 /**
355 * Add new node.
356 *
357 * @param array $node An array that contains:
358 * 'type' => 1 - warning, 2 - hidden warning that will be shown using JS, 3 - info message
359 * 'data': @see WP_Admin_Bar->add_node
360 * @param object $wp_admin_bar
361 */
362 $nodes = apply_filters( 'advanced-ads-ad-health-nodes', $nodes );
363
364 usort( $nodes, [ $this, 'sort_nodes' ] );
365
366 // load number of already detected notices.
367 $notices = Advanced_Ads_Ad_Health_Notices::get_number_of_notices();
368
369 if ( ! advads_is_amp() ) {
370 $warnings = 0; // Will be updated using JS.
371 } else {
372 $warnings = $this->count_visible_warnings( $nodes, [ 1 ] );
373 }
374
375 $issues = $warnings;
376
377 $this->add_header_nodes( $wp_admin_bar, $issues, $notices );
378
379 foreach ( $nodes as $node ) {
380 if ( isset( $node['data'] ) ) {
381 $wp_admin_bar->add_node( $node['data'] );
382 }
383 }
384
385 $this->add_footer_nodes( $wp_admin_bar, $issues );
386 }
387
388
389 /**
390 * Add classes to the `body` tag.
391 *
392 * @param string[] $classes Array of existing class names.
393 * @return string[] $classes Array of existing and new class names.
394 */
395 public function body_class( $classes ) {
396 $aa_classes = [
397 'aa-prefix-' . Advanced_Ads_Plugin::get_instance()->get_frontend_prefix(),
398 ];
399
400 $disabled_reason = Advanced_Ads::get_instance()->disabled_reason;
401 if ( $disabled_reason ) {
402 $aa_classes[] = 'aa-disabled-' . esc_attr( $disabled_reason );
403 }
404
405 global $post;
406 if ( ! empty( $post->ID ) ) {
407 $ad_settings = get_post_meta( $post->ID, '_advads_ad_settings', true );
408 if ( ! empty( $ad_settings['disable_the_content'] ) ) {
409 $aa_classes[] = 'aa-disabled-content';
410 }
411 }
412
413 // hide-ads-from-bots option is enabled
414 $options = Advanced_Ads_Plugin::get_instance()->options();
415 if ( ! empty( $options['block-bots'] ) ) {
416 $aa_classes[] = 'aa-disabled-bots';
417 }
418
419 $aa_classes = apply_filters( 'advanced-ads-body-classes', $aa_classes );
420
421 if ( ! is_array( $classes ) ) {
422 $classes = [];
423 }
424 if ( ! is_array( $aa_classes ) ) {
425 $aa_classes = [];
426 }
427
428 return array_merge( $classes, $aa_classes );
429 }
430
431
432
433
434 /**
435 * Count visible notices and warnings.
436 *
437 * @param array $nodes Nodes to add.
438 * @param array $types Warning types.
439 */
440 private function count_visible_warnings( $nodes, $types = [] ) {
441 $warnings = 0;
442 foreach ( $nodes as $node ) {
443 if ( ! isset( $node['type'] ) || ! isset( $node['data'] ) ) { continue; }
444 if ( in_array( $node['type'], $types ) ) {
445 $warnings++;
446 }
447 }
448 return $warnings;
449 }
450
451 /**
452 * Add header nodes.
453 *
454 * @param object $wp_admin_bar WP_Admin_Bar object.
455 * @param int $issues Number of all issues.
456 * @param int $notices Number of notices.
457 */
458 private function add_header_nodes( $wp_admin_bar, $issues, $notices ) {
459 $wp_admin_bar->add_node( [
460 'id' => 'advanced_ads_ad_health',
461 'title' => __( 'Ad Health', 'advanced-ads' ) . '&nbsp;<span class="advanced-ads-issue-counter">' . $issues . '</span>',
462 'parent' => false,
463 'href' => admin_url( 'admin.php?page=advanced-ads' ),
464 'meta' => [
465 'class' => $issues ? 'advads-adminbar-is-warnings': '',
466 ],
467 ] );
468
469
470 // show that there are backend notices
471 if ( $notices ) {
472 $wp_admin_bar->add_node( [
473 'parent' => 'advanced_ads_ad_health',
474 'id' => 'advanced_ads_ad_health_more',
475 'title' => sprintf(__( 'Show %d more notifications', 'advanced-ads' ), absint( $notices ) ),
476 'href' => admin_url( 'admin.php?page=advanced-ads' ),
477 ] );
478 }
479 }
480
481 /**
482 * Add footer nodes.
483 *
484 * @param obj $wp_admin_bar WP_Admin_Bar object.
485 * @param int $issues Number of all issues.
486 */
487 private function add_footer_nodes( $wp_admin_bar, $issues ) {
488 if ( ! $issues ) {
489 $wp_admin_bar->add_node( [
490 'parent' => 'advanced_ads_ad_health',
491 'id' => 'advanced_ads_ad_health_fine',
492 'title' => __( 'Everything is fine', 'advanced-ads' ),
493 'href' => false,
494 'meta' => [
495 'target' => '_blank',
496 ]
497 ] );
498 }
499
500 $wp_admin_bar->add_node( [
501 'parent' => 'advanced_ads_ad_health',
502 'id' => 'advanced_ads_ad_health_support',
503 'title' => __( 'Get help', 'advanced-ads' ),
504 'href' => Advanced_Ads_Plugin::support_url( '?utm_source=advanced-ads&utm_medium=link&utm_campaign=health-support' ),
505 'meta' => [
506 'target' => '_blank',
507 ]
508 ] );
509 }
510
511 /**
512 * Filter out nodes intended to AMP pages only.
513 *
514 * @param array $nodes Nodes to add.
515 * @return array $nodes Nodes to add.
516 */
517 private function filter_nodes( $nodes ) {
518 return $nodes;
519 }
520
521 /**
522 * Sort nodes.
523 */
524 function sort_nodes( $a, $b ) {
525 if ( ! isset( $a['type'] ) || ! isset( $b['type'] ) ) {
526 return 0;
527 }
528 if ( $a['type'] == $b['type'] ) {
529 return 0;
530 }
531 return ( $a['type'] < $b['type'] ) ? -1 : 1;
532 }
533
534 /**
535 * Set variable to 'true' when 'the_content' filter is invoked.
536 *
537 * @param string $content
538 * @return string $content
539 */
540 public function set_did_the_content( $content ) {
541 if ( ! $this->did_the_content ) {
542 $this->did_the_content = true;
543 }
544
545 if ( Advanced_Ads::get_instance()->has_many_the_content() ) {
546 $this->has_many_the_content = true;
547 }
548 return $content;
549 }
550
551 /**
552 * Check conditions and display warning.
553 * Conditions:
554 * AdBlocker enabled,
555 * jQuery is included in header
556 * AdSense Quick Start ads are running
557 */
558 public function footer_checks() {
559 ob_start();
560 ?><!-- Advanced Ads: <?php esc_html_e( 'the following code is used for automatic error detection and only visible to admins', 'advanced-ads' ); ?>-->
561 <style>#wp-admin-bar-advanced_ads_ad_health .hidden { display: none; }
562 #wp-admin-bar-advanced_ads_ad_health-default a:after { content: "\25BA"; margin-left: .5em; font-size: smaller; }
563 #wp-admin-bar-advanced_ads_ad_health-default .advanced_ads_ad_health_highlight_ads div:before { content: "\f177"; margin-right: .2em; line-height: 1em; padding: 0.2em 0 0; color: inherit; }
564 #wp-admin-bar-advanced_ads_ad_health-default .advanced_ads_ad_health_highlight_ads div:hover { color: #00b9eb; cursor: pointer; }
565 #wpadminbar .advanced-ads-issue-counter { background-color: #d54e21; display: none; padding: 1px 7px 1px 6px!important; border-radius: 50%; color: #fff; }
566 #wpadminbar .advads-adminbar-is-warnings .advanced-ads-issue-counter { display: inline; }
567 .advanced-ads-highlight-ads { outline:4px solid #0474A2 !important; }
568
569 .advads-frontend-notice { display: none; position: fixed; top: 0; z-index: 1000; left: 50%; max-width: 500px; margin-left: -250px; padding: 30px 10px 10px 10px; border: 0px solid #0074a2; border-top: 0; border-radius: 0px 0px 5px 5px; box-shadow: 0px 0px 15px rgba(0,0,0,0.3); background: #ffffff; background: rgba(255,255,255,0.95); font-size: 16px; font-family: Arial, Verdana, sans-serif; line-height: 1.5em; color: #444444; }
570
571 .advads-frontend-notice a, .advads-frontend-notice a:link { color: #0074a2; text-decoration: none; }
572 .advads-frontend-notice ul { }
573 .advads-frontend-notice ul li { line-height: 1.5em; }
574
575 .advads-frontend-notice .advads-close-notice { position: absolute; top: 5px; right: 0; display: block; font-size: 20px; width: 30px; height: 30px; line-height: 30px; text-decoration: none; text-align: center; font-weight: bold; color: #444444; cursor: pointer; }
576 .advads-frontend-notice .advads-notice-var1 { font-size: 14px; font-style: italic; text-align: center; text-align: 1.3em; }
577 .advads-frontend-notice .advads-frontend-notice-choice { text-align: center; }
578 .advads-frontend-notice .advads-frontend-notice-choice:after { display: block; content: " "; clear: both; }
579
580 /* CSS Smilies */
581 .advads-smiley { position: relative; display: inline-block; border: 4px solid #0074a2; border-radius: 50px; width: 65px; height: 65px; background: #ffffff; cursor: pointer; margin: 0px 15px 5px 0px; }
582 .advads-smiley:hover { transform: scale(0.90); transition: all linear 0.3s; }
583 .advads-smiley .eye { display: block; position: absolute; top: 25%; width: 18%; height: 18%; background: #0074a2; border-radius: 50%; }
584 .advads-smiley .eye1 { left: 20%; }
585 .advads-smiley .eye2 { right: 20%; }
586 .advads-smiley .mouth { display: block; position: absolute; left: 20%; top: 15%; width: 60%; height: 60%; border-bottom: 5px solid #0074a2; background: none; }
587
588 /* CSS smiley: negative */
589 .advads-smiley-negative { /* border-color: #9a2d18; */ }
590 .advads-smiley-negative .mouth { top: 50%; border: 5px solid #0074a2; width: 60%px; height: 60%; transform: rotate(-45deg); border-bottom-color: transparent; border-left-color: transparent; border-radius: 50%; }
591
592 /* CSS smiley: positive */
593 .advads-smiley-positive { /* border-color: #1e610f; */ }
594 .advads-smiley-positive .mouth { top: 25%; border: 5px solid #0074a2; width: 60%px; height: 60%; transform: rotate(-45deg); border-top-color: transparent; border-right-color: transparent; border-radius: 50%; }
595
596 /* CSS smiley: neutral */
597 .advads-smiley-laugh .mouth { top: 25%; border-radius: 50%; }
598
599 @media screen and (max-width: 510px) {
600 .advads-frontend-notice { left: 0; width: 100%; margin-left: 0; }
601 .advads-smiley { width: 45px; height: 45px; }
602 }
603 </style>
604 <?php echo ob_get_clean();
605
606 if ( advads_is_amp() ) {
607 return;
608 }
609
610 $adsense_options = Advanced_Ads_AdSense_Data::get_instance()->get_options();
611 ob_start();
612 ?><script type="text/javascript" src="<?php echo ADVADS_BASE_URL . 'admin/assets/js/advertisement.js' ?>"></script>
613 <script>
614 var advanced_ads_frontend_checks = {
615 showCount: function() {
616 try {
617 // Count only warnings that have the 'advanced_ads_ad_health_warning' class.
618 var warning_count = document.querySelectorAll( '.advanced_ads_ad_health_warning:not(.hidden)' ).length;
619 var fine_item = document.getElementById( 'wp-admin-bar-advanced_ads_ad_health_fine' );
620 } catch ( e ) { return; }
621
622 var header = document.querySelector( '#wp-admin-bar-advanced_ads_ad_health > a' );
623 if ( warning_count ) {
624 if ( fine_item ) {
625 // Hide 'fine' item.
626 fine_item.className += ' hidden';
627 }
628
629 if ( header ) {
630 header.innerHTML = header.innerHTML.replace(/<span class="advanced-ads-issue-counter">\d*<\/span>/, '') + '<span class="advanced-ads-issue-counter">' + warning_count + '</span>';
631 // add class
632 header.className += ' advads-adminbar-is-warnings';
633 }
634 } else {
635 // Show 'fine' item.
636 if ( fine_item ) {
637 fine_item.classList.remove('hidden');
638 }
639
640 // Remove counter.
641 if ( header ) {
642 header.innerHTML = header.innerHTML.replace(/<span class="advanced-ads-issue-counter">\d*<\/span>/, '');
643 header.classList.remove('advads-adminbar-is-warnings');
644 }
645 }
646 },
647
648 array_unique: function( array ) {
649 var r= [];
650 for ( var i = 0; i < array.length; i++ ) {
651 if ( r.indexOf( array[ i ] ) === -1 ) {
652 r.push( array[ i ] );
653 }
654 }
655 return r;
656 },
657
658 /**
659 * Add item to Ad Health node.
660 *
661 * @param string selector Selector of the node.
662 * @param string/array item item(s) to add.
663 */
664 add_item_to_node: function( selector, item ) {
665 if ( typeof item === 'string' ) {
666 item = item.split();
667 }
668 var selector = document.querySelector( selector );
669 if ( selector ) {
670 selector.className = selector.className.replace( 'hidden', '' );
671 selector.innerHTML = selector.innerHTML.replace( /(<i>)(.*?)(<\/i>)/, function( match, p1, p2, p3 ) {
672 p2 = ( p2 ) ? p2.split( ', ' ) : [];
673 p2 = p2.concat( item );
674 p2 = advanced_ads_frontend_checks.array_unique( p2 );
675 return p1 + p2.join( ', ' ) + p3;
676 } );
677 advanced_ads_frontend_checks.showCount();
678 }
679 },
680
681 /**
682 * Add item to Ad Health notices in the backend
683 *
684 * @param key of the notice
685 * @param attr
686 * @returns {undefined}
687 */
688 add_item_to_notices: function( key, attr = '' ) {
689 var cookie = advads.get_cookie( 'advanced_ads_ad_health_notices' );
690 if( cookie ){
691 advads_cookie_notices = JSON.parse( cookie );
692 } else {
693 advads_cookie_notices = new Array();
694 }
695 // stop if notice was added less than 1 hour ago
696 if( 0 <= advads_cookie_notices.indexOf( key ) ){
697 return;
698 }
699 var query = {
700 action: 'advads-ad-health-notice-push',
701 key: key,
702 attr: attr,
703 nonce: '<?php echo wp_create_nonce('advanced-ads-ad-health-ajax-nonce'); ?>'
704 };
705 // send query
706 // update notices and cookie
707 jQuery.post( advads_frontend_checks.ajax_url, query, function (r) {
708 advads_cookie_notices.push( key );
709 var notices_str = JSON.stringify( advads_cookie_notices );
710 advads.set_cookie_sec( 'advanced_ads_ad_health_notices', notices_str, 3600 ); // 1 hour
711 });
712 },
713 /**
714 * Update status of frontend notices
715 *
716 * @param key of the notice
717 * @param attr
718 * @returns {undefined}
719 */
720 update_frontend_notices: function( key, attr = '' ) {
721 var query = {
722 action: 'advads-ad-frontend-notice-update',
723 key: key,
724 attr: attr,
725 nonce: '<?php echo wp_create_nonce('advanced-ads-frontend-notice-nonce'); ?>'
726 };
727 // send query
728 jQuery.post( advads_frontend_checks.ajax_url, query, function (r) {})
729 // close message when done.
730 .done(function() {
731 content_obj.slideUp();
732 });
733 },
734
735 /**
736 * Search for hidden AdSense.
737 *
738 * @param string context Context for search.
739 */
740 advads_highlight_hidden_adsense: function( context ) {
741 if ( ! context ) {
742 context = 'html'
743 }
744 if ( window.jQuery ) {
745 var responsive_zero_width = [];
746 jQuery( 'ins.adsbygoogle', context ).each( function() {
747 // Zero width, perhaps because a parent container is floated
748 if ( jQuery( this ).attr( 'data-ad-format' ) && 0 === jQuery( this ).width() ) {
749 responsive_zero_width.push( this.dataset.adSlot );
750 }
751 });
752 if ( responsive_zero_width.length ) {
753 advanced_ads_frontend_checks.add_item_to_node( '.advanced_ads_ad_health_floated_responsive_adsense', responsive_zero_width );
754 }
755 }
756 }
757 };
758
759 (function(d, w) {
760 // var not_head_jQuery = typeof jQuery === 'undefined';
761
762 var addEvent = function( obj, type, fn ) {
763 if ( obj.addEventListener )
764 obj.addEventListener( type, fn, false );
765 else if ( obj.attachEvent )
766 obj.attachEvent( 'on' + type, function() { return fn.call( obj, window.event ); } );
767 };
768
769 // highlight ads that use Advanced Ads placements or AdSense Auto ads
770 function highlight_ads() {
771 /**
772 * Selectors:
773 * Placement container: div[id^="<?php echo Advanced_Ads_Plugin::get_instance()->get_frontend_prefix();?>"]
774 * AdSense Auto ads: 'google-auto-placed'
775 */
776 try {
777 var ad_wrappers = document.querySelectorAll('div[id^="<?php echo Advanced_Ads_Plugin::get_instance()->get_frontend_prefix();?>"],.google-auto-placed')
778 } catch ( e ) { return; }
779 for ( i = 0; i < ad_wrappers.length; i++ ) {
780 ad_wrappers[i].title = ad_wrappers[i].className;
781 ad_wrappers[i].className += ' advanced-ads-highlight-ads';
782 // in case we want to remove it later
783 // ad_wrappers[i].className = ad_wrappers[i].className.replace( 'advanced-ads-highlight-ads', '' );
784 }
785 }
786
787 advanced_ads_ready( function() {
788 var adblock_item = d.getElementById( 'wp-admin-bar-advanced_ads_ad_health_adblocker_enabled' );
789 // jQuery_item = d.getElementById( 'wp-admin-bar-advanced_ads_ad_health_jquery' ),
790
791 // handle click on the highlight_ads link
792 var highlight_link = d.getElementById( 'wp-admin-bar-advanced_ads_ad_health_highlight_ads' );
793 addEvent( highlight_link, 'click', highlight_ads );
794
795 if ( adblock_item && typeof advanced_ads_adblocker_test === 'undefined' ) {
796 // show hidden item
797 adblock_item.className = adblock_item.className.replace( /hidden/, '' );
798 }
799
800 /* if ( jQuery_item && not_head_jQuery ) {
801 // show hidden item
802 jQuery_item.className = jQuery_item.className.replace( /hidden/, '' );
803 }*/
804
805 <?php if ( ! $this->did_the_content ) : ?>
806 var the_content_item = d.getElementById( 'wp-admin-bar-advanced_ads_ad_health_the_content_not_invoked' );
807 if ( the_content_item ) {
808 the_content_item.className = the_content_item.className.replace( /hidden/, '' );
809 }
810 <?php endif; ?>
811
812 advanced_ads_frontend_checks.showCount();
813 });
814
815 <?php if( ! isset( $adsense_options['violation-warnings-disable'] ) ) : ?>
816 // show warning if AdSense ad is hidden
817 // show hint if AdSense Auto ads are enabled
818 setTimeout( function(){
819 advanced_ads_ready( advanced_ads_frontend_checks.advads_highlight_hidden_adsense );
820 }, 2000 );
821
822 // highlight AdSense Auto Ads ads 3 seconds after site loaded
823 setTimeout( function(){
824 advanced_ads_ready( advads_highlight_adsense_autoads );
825 }, 3000 );
826 function advads_highlight_adsense_autoads(){
827 if ( ! window.jQuery ) {
828 window.console && window.console.log( 'Advanced Ads: jQuery not found. Some Ad Health warnings will not be displayed.' );
829 return;
830 }
831 var autoads_ads = document.querySelectorAll('.google-auto-placed');
832 // show Auto Ads warning in Ad Health bar if relevant
833 if( autoads_ads.length ){
834 var advads_autoads_link = document.querySelector( '#wp-admin-bar-advanced_ads_autoads_displayed.hidden' );
835 if ( advads_autoads_link ) {
836 advads_autoads_link.className = advads_autoads_link.className.replace( 'hidden', '' );
837 }
838 advanced_ads_frontend_checks.showCount();
839 }
840 }
841
842 // show notice
843 // @param notice
844 function advads_frontend_notice( notice = '' ){
845 var content = '';
846 switch ( notice ) {
847 case 'auto-ads-with-ads' :
848 var autoads_ads = jQuery(document).find('.google-auto-placed');
849 <?php
850 $current_user = wp_get_current_user();
851 $current_user_nicename = isset( $current_user->user_nicename ) ? $current_user->user_nicename : 'admin';
852 ?>
853 content = '' +
854 '<p style="text-align: center;"><strong><?php printf( __( 'Hi %s', 'advanced-ads'), $current_user_nicename ); ?></strong><br><?php printf( __( 'Advanced Ads detected AdSense Auto ads (%sx) on this page.', 'advanced-ads' ), 'AUTO_ADS_NUM' ); ?><br><?php esc_attr_e( 'Is that correct?', 'advanced-ads' ); ?></p>' +
855 '<div class="advads-frontend-notice-choice">' +
856 '<span class="advads-close advads-smiley advads-smiley-positive" title="<?php esc_attr_e( 'All is fine', 'advanced-ads' ); ?>"><i class="eye eye1"></i><i class="eye eye2"></i><i class="mouth"></i></span>' +
857 '<span class="advads-choice-negative advads-smiley" title="<?php esc_attr_e( 'Something is off', 'advanced-ads' ); ?>"><i class="eye eye1"></i><i class="eye eye2"></i><i class="mouth"></i></span>' +
858 '</div>' +
859 '<p class="advads-notice-var1"><?php esc_attr_e( 'PS: This is a one-time check from your friendly Advanced Ads plugin. It is only visible to you.', 'advanced-ads' ); ?></p>';
860 // dynamically add the number of Auto ads found.
861 content = content.replace( 'AUTO_ADS_NUM', autoads_ads.length );
862 break;
863 case 'auto-ads-without-ads' :
864 <?php
865 $current_user = wp_get_current_user();
866 $current_user_nicename = isset( $current_user->user_nicename ) ? $current_user->user_nicename : 'admin';
867 ?>
868 content = '' +
869 '<p style="text-align: center;"><strong><?php printf( __( 'Hi %s', 'advanced-ads'), $current_user_nicename ); ?></strong><br><?php printf( __( 'Advanced Ads detected the AdSense Auto ads code and <strong>no ads on this page</strong>.', 'advanced-ads' ) ); ?><br/><?php esc_attr_e( 'Is that correct?', 'advanced-ads' ); ?></p>' +
870 '<div class="advads-frontend-notice-choice">' +
871 '<span class="advads-close advads-smiley advads-smiley-positive" title="<?php esc_attr_e( 'This is fine', 'advanced-ads' ); ?>"><i class="eye eye1"></i><i class="eye eye2"></i><i class="mouth"></i></span>' +
872 '<span class="advads-choice-negative advads-smiley" title="<?php esc_attr_e( 'I expected something else', 'advanced-ads' ); ?>"><i class="eye eye1"></i><i class="eye eye2"></i><i class="mouth"></i></span>' +
873 '</div>' +
874 '<p class="advads-notice-var1"><?php esc_attr_e( 'PS: This is a one-time check from your friendly Advanced Ads plugin. It is only visible to you.', 'advanced-ads' ); ?></p>';
875 break;
876 case 'auto-ads-with-ads-help' :
877 content = '<p style="text-align: center;"><?php esc_attr_e( 'Just click on your problem to learn more from our knowledge base.', 'advanced-ads' ); ?></p>' +
878 '<ul><li><a href="<?php echo esc_url( ADVADS_URL ); ?>adsense-in-random-positions-auto-ads/?utm_source=advanced-ads&utm_medium=link&utm_campaign=frontend-auto-ads-disable#How_to_disable_Auto_Ads" target="_blank"><?php esc_attr_e( 'I want to disable AdSense Auto ads', 'advanced-ads' ); ?></a></li>' +
879 '<li><a href="<?php echo esc_url( ADVADS_URL ); ?>manual/adsense-auto-ads-not-showing/?utm_source=advanced-ads&utm_medium=link&utm_campaign=frontend-auto-ads" target="_blank"><?php esc_attr_e( 'I don’t see any Auto ads', 'advanced-ads' ); ?></a></li>' +
880 '<li><a href="<?php echo esc_url( ADVADS_URL ); ?>manual/adsense-auto-ads-not-showing/?utm_source=advanced-ads&utm_medium=link&utm_campaign=frontend-auto-ads-blank#Auto_ads_stay_blank" target="_blank"><?php esc_attr_e( 'I only see blank space', 'advanced-ads' ); ?></a></li>' +
881 '<li><a href="<?php echo esc_url( ADVADS_URL ); ?>place-adsense-ad-unit-manually/?utm_source=advanced-ads&utm_medium=link&utm_campaign=frontend-auto-ads-position" target="_blank"><?php esc_attr_e( 'I want to change the position of the ads', 'advanced-ads' ); ?></a></li>' +
882 '<li><a href="<?php echo esc_url( ADVADS_URL ); ?>adsense-auto-ads-wordpress/?utm_source=advanced-ads&utm_medium=link&utm_campaign=frontend-auto-ads-specific-pages#Display_Auto_Ads_only_on_specific_pages" target="_blank"><?php esc_attr_e( 'Display Auto ads only on specific pages', 'advanced-ads' ); ?></a></li></ul>';
883 break;
884 case 'auto-ads-without-ads-help' :
885 content = '<p style="text-align: center;"><?php esc_attr_e( 'Just click on your problem to learn more from our knowledge base.', 'advanced-ads' ); ?></p>' +
886 '<ul><li><a href="<?php echo esc_url( ADVADS_URL ); ?>manual/adsense-auto-ads-not-showing/?utm_source=advanced-ads&utm_medium=link&utm_campaign=frontend-no-auto-ads" target="_blank"><?php esc_attr_e( 'I don’t see any Auto ads', 'advanced-ads' ); ?></a></li>' +
887 '<li><a href="<?php echo esc_url( ADVADS_URL ); ?>manual/adsense-auto-ads-not-showing/?utm_source=advanced-ads&utm_medium=link&utm_campaign=frontend-no-auto-ads-check-code#Check_if_the_Auto_ads_code_exists" target="_blank"><?php esc_attr_e( 'How to look for the Auto ads code', 'advanced-ads' ); ?></a></li>' +
888 '<li><a href="<?php echo esc_url( ADVADS_URL ); ?>support/?utm_source=advanced-ads&utm_medium=link&utm_campaign=frontend-no-auto-ads-support" target="_blank"><?php esc_attr_e( 'I have another question or problem', 'advanced-ads' ); ?></a></li></ul>';
889 break;
890 case 'closing' : // show until message is closed.
891 content = '<p><?php esc_attr_e( 'Closing the message', 'advanced-ads' ); ?>...</p>';
892 break;
893 }
894 if( content ){
895 // get existing content box or create new one.
896 if( jQuery( '.advads-frontend-notice' ).length ){
897 content_obj = jQuery( '.advads-frontend-notice' );
898 } else {
899 content_obj = jQuery( '<div class="advads-frontend-notice" data-choice="' + notice + '" style="display: none;"><span class="advads-close advads-close-notice">✕</span><div class="advads-content"></div></div>' );
900 }
901 // add content to the box.
902 content_obj.find( '.advads-content' ).html( content );
903 if( document.getElementById( 'wpadminbar' ) ){
904 content_obj.css( 'top', jQuery( '#wpadminbar' ).height() );
905 }
906 jQuery( content_obj ).appendTo( 'body' ).slideDown();
907 // register close event
908 content_obj.on( 'click', '.advads-close', function(){
909 // get notice
910 if( content_obj.data( 'choice' ) ){
911 advads_frontend_notice( 'closing' );
912 advanced_ads_frontend_checks.update_frontend_notices( content_obj.data( 'choice' ) );
913 }
914 // message is hidden in update_frontend_notices
915 });
916 // register button choice
917 jQuery( '.advads-frontend-notice[data-choice="auto-ads-with-ads"]' ).on( 'click', '.advads-choice-negative', function(){
918 advads_frontend_notice( 'auto-ads-with-ads-help' );
919 });
920 jQuery( '.advads-frontend-notice[data-choice="auto-ads-without-ads"]' ).on( 'click', '.advads-choice-negative', function(){
921 advads_frontend_notice( 'auto-ads-without-ads-help' );
922 });
923 }
924 }
925 <?php endif;
926 /**
927 * Code to check if current user gave consent to show ads
928 */
929 $privacy = Advanced_Ads_Privacy::get_instance();
930 if ( 'not_needed' !== $privacy->get_state() ) :
931 ?>
932 document.addEventListener('advanced_ads_privacy', function (event) {
933 var advads_consent_link = document.querySelector('#wp-admin-bar-advanced_ads_ad_health_consent_missing');
934
935 if (!advads_consent_link) {
936 return;
937 }
938
939 if (event.detail.state !== 'accepted' && event.detail.state !== 'not_needed') {
940 advads_consent_link.classList.remove('hidden');
941 } else {
942 advads_consent_link.classList.add('hidden');
943 }
944
945 advanced_ads_frontend_checks.showCount();
946 });
947 <?php
948 endif;
949 $privacy_options = $privacy->options();
950 if (
951 ( empty( $privacy_options['enabled'] ) || $privacy_options['consent-method'] !== 'iab_tcf_20' )
952 && (bool) apply_filters( 'advanced-ads-ad-health-show-tcf-notice', true )
953 ) :
954 ?>
955 var count = 0,
956 tcfapiInterval = setInterval(function () {
957 if (++count === 600) {
958 clearInterval(tcfapiInterval);
959 }
960 if (typeof window.__tcfapi === 'undefined') {
961 return;
962 }
963 clearInterval(tcfapiInterval);
964
965 var advads_privacy_link = document.querySelector('#wp-admin-bar-advanced_ads_ad_health_privacy_disabled');
966
967 if (!advads_privacy_link) {
968 return;
969 }
970
971 advads_privacy_link.classList.remove('hidden');
972
973 advanced_ads_frontend_checks.showCount();
974 }, 100);
975 <?php endif; ?>
976 /**
977 * show Google Ad Manager debug link in Ad Health
978 *
979 * look for container with ID starting with `div-gpt-ad-`
980 * or `gpt-ad-` as used by our own Google Ad Manager integration
981 * we don’t look for the gpt header script because that is also used by other services that are based on Google Publisher Tags
982 */
983 function advads_gam_show_debug_link(){
984 var advads_gam_debug_link = document.querySelector( '.advanced_ads_ad_health_gam_debug_link.hidden' );
985
986 if( ! advads_gam_debug_link ){
987 return;
988 }
989
990 // initialized by the GAM header tag or inline body tags
991 if ( document.querySelector( '[id^="div-gpt-ad-"],[id^="gpt-ad-"]' ) ) {
992 advads_gam_debug_link.className = advads_gam_debug_link.className.replace( 'hidden', '' );
993 }
994 }
995 // look for Google Ad Manager tags with a delay of 2 seconds
996 setTimeout( function(){
997 advanced_ads_ready( advads_gam_show_debug_link );
998 }, 2000 );
999 })(document, window);
1000 </script>
1001 <?php echo Advanced_Ads_Utils::get_inline_asset( ob_get_clean() );
1002 }
1003
1004 /**
1005 * Inject JS after ad content.
1006 *
1007 * @param str $content ad content
1008 * @param obj $ad Advanced_Ads_Ad
1009 * @return str $content ad content
1010 */
1011 public function after_ad_output( $content, Advanced_Ads_Ad $ad ) {
1012 if ( ! isset( $ad->args['frontend-check'] ) ) { return $content; }
1013
1014 if ( advads_is_amp() ) {
1015 return $content;
1016 }
1017
1018 if ( Advanced_Ads_Ad_Debug::is_https_and_http( $ad ) ) {
1019 ob_start(); ?>
1020 <script>advanced_ads_ready( function() {
1021 var ad_id = '<?php echo $ad->id; ?>';
1022 advanced_ads_frontend_checks.add_item_to_node( '.advanced_ads_ad_health_has_http', ad_id );
1023 advanced_ads_frontend_checks.add_item_to_notices( 'ad_has_http', { append_key: ad_id, ad_id: ad_id } );
1024 });</script>
1025 <?php
1026 $content .= Advanced_Ads_Utils::get_inline_asset( ob_get_clean() );
1027 }
1028
1029 if ( ! Advanced_Ads_Frontend_Checks::can_use_head_placement( $content, $ad ) ) {
1030 ob_start(); ?>
1031 <script>advanced_ads_ready( function() {
1032 var ad_id = '<?php echo $ad->id; ?>';
1033 advanced_ads_frontend_checks.add_item_to_node( '.advanced_ads_ad_health_incorrect_head', ad_id );
1034 advanced_ads_frontend_checks.add_item_to_notices( 'ad_with_output_in_head', { append_key: ad_id, ad_id: ad_id } );
1035 });</script>
1036 <?php
1037 $content .= Advanced_Ads_Utils::get_inline_asset( ob_get_clean() );
1038 }
1039
1040 $adsense_options = Advanced_Ads_AdSense_Data::get_instance()->get_options();
1041 if ( 'adsense' === $ad->type
1042 && ! empty( $ad->args['cache_busting_elementid'] )
1043 && ! isset( $adsense_options['violation-warnings-disable'] )
1044 ) {
1045 ob_start(); ?>
1046 <script>advanced_ads_ready( function() {
1047 var ad_id = '<?php echo $ad->id; ?>';
1048 var wrapper = '#<?php echo $ad->args['cache_busting_elementid']; ?>';
1049 advanced_ads_frontend_checks.advads_highlight_hidden_adsense( wrapper );
1050 });</script>
1051 <?php
1052 $content .= Advanced_Ads_Utils::get_inline_asset( ob_get_clean() );
1053 }
1054
1055 return $content;
1056 }
1057
1058
1059 /**
1060 * Check if the 'Header Code' placement can be used to delived the ad.
1061 *
1062 * @param string $content Ad content.
1063 * @param Advanced_Ads_Ad $ad Advanced_Ads_Ad.
1064 * @return bool
1065 */
1066 public static function can_use_head_placement( $content, Advanced_Ads_Ad $ad ) {
1067
1068 if ( ! $ad->is_head_placement ) {
1069 return true;
1070 }
1071
1072 // strip linebreaks, because, a line break after a comment is identified as a text node.
1073 $content = preg_replace( "/\r|\n/", "", $content );
1074
1075 if ( ! $dom = self::get_ad_dom( $content ) ) {
1076 return true;
1077 }
1078
1079 $body = $dom->getElementsByTagName( 'body' )->item( 0 );
1080
1081 $count = $body->childNodes->length;
1082 for ( $i = 0; $i < $count; $i++ ) {
1083 $node = $body->childNodes->item( $i );
1084
1085 if ( XML_TEXT_NODE === $node->nodeType ) {
1086 return false;
1087 }
1088
1089 if ( XML_ELEMENT_NODE === $node->nodeType
1090 && ! in_array( $node->nodeName, [ 'meta', 'link', 'title', 'style', 'script', 'noscript', 'base' ] ) ) {
1091 return false;
1092 }
1093 }
1094 return true;
1095 }
1096
1097 /**
1098 * Convert ad content to a DOMDocument.
1099 *
1100 * @param string $content
1101 * @return DOMDocument|false
1102 */
1103 private static function get_ad_dom( $content ) {
1104 if ( ! extension_loaded( 'dom' ) ) {
1105 return false;
1106 }
1107 $libxml_previous_state = libxml_use_internal_errors( true );
1108 $dom = new DOMDocument();
1109 $result = $dom->loadHTML( '<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body>' . $content . '</body></html>' );
1110
1111 libxml_clear_errors();
1112 libxml_use_internal_errors( $libxml_previous_state );
1113
1114 if ( ! $result ) {
1115 return false;
1116 }
1117
1118 return $dom;
1119 }
1120
1121 /**
1122 * Check if at least one placement uses `the_content`.
1123 *
1124 * @return bool True/False.
1125 */
1126 private function has_the_content_placements() {
1127 $placements = Advanced_Ads::get_ad_placements_array();
1128 $placement_types = Advanced_Ads_Placements::get_placement_types();
1129 // Find a placement that depends on 'the_content' filter.
1130 foreach ( $placements as $placement ) {
1131 if ( isset ( $placement['type'] )
1132 && ! empty( $placement_types[ $placement['type'] ]['options']['uses_the_content'] ) ) {
1133 return true;
1134 }
1135 }
1136 return false;
1137 }
1138 }
1139