PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 14.4.2
Jetpack – WP Security, Backup, Speed, & Growth v14.4.2
12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 14.1.1 14.2.2 14.3.1 14.4.2 14.5.1 14.6.1 14.7.1 14.8.1 14.9.2 15.0.3 15.1.2 15.2.1 15.3.2 15.4.1 15.5.1 15.6.1 15.7.2 15.8.1 15.9.2 16.0.2 16.1.3 16.2-a.5 16.2-a.3 16.1.2 16.2-a.1 16.1.1 16.1 16.1-beta 16.1-beta.2 16.1-beta.3 16.1-a.5 16.1-a.3 16.0.1 16.1-a.1 16.0 16.0-beta 16.0-a.7 16.0-a.5 15.9.1 16.0-a.3 16.0-a.1 15.9 15.9-beta 15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / modules / wordads / class-wordads.php
jetpack / modules / wordads Last commit date
css 5 years ago js 1 year ago php 1 year ago class-wordads.php 1 year ago
class-wordads.php
1000 lines
1 <?php
2 /**
3 * Main WordAds file.
4 *
5 * @package automattic/jetpack
6 */
7
8 use Automattic\Jetpack\Status\Host;
9
10 define( 'WORDADS_ROOT', __DIR__ );
11 define( 'WORDADS_BASENAME', plugin_basename( __FILE__ ) );
12 define( 'WORDADS_FILE_PATH', WORDADS_ROOT . '/' . basename( __FILE__ ) );
13 define( 'WORDADS_URL', plugins_url( '/', __FILE__ ) );
14 define( 'WORDADS_API_TEST_ID', '26942' );
15 define( 'WORDADS_API_TEST_ID2', '114160' );
16
17 require_once WORDADS_ROOT . '/php/class-wordads-sidebar-widget.php';
18 require_once WORDADS_ROOT . '/php/class-wordads-api.php';
19 require_once WORDADS_ROOT . '/php/class-wordads-cron.php';
20 require_once WORDADS_ROOT . '/php/class-wordads-california-privacy.php';
21 require_once WORDADS_ROOT . '/php/class-wordads-ccpa-do-not-sell-link-widget.php';
22 require_once WORDADS_ROOT . '/php/class-wordads-consent-management-provider.php';
23 require_once WORDADS_ROOT . '/php/class-wordads-smart.php';
24 require_once WORDADS_ROOT . '/php/class-wordads-shortcode.php';
25
26 /**
27 * Primary WordAds class.
28 */
29 class WordAds {
30
31 /**
32 * Ads parameters.
33 *
34 * @var null
35 */
36 public $params = null;
37
38 /**
39 * Ads.
40 *
41 * @var array
42 */
43 public $ads = array();
44
45 /**
46 * Array of supported ad types.
47 *
48 * @var array
49 */
50 public static $ad_tag_ids = array(
51 'mrec' => array(
52 'tag' => '300x250_mediumrectangle',
53 'height' => '250',
54 'width' => '300',
55 ),
56 'leaderboard' => array(
57 'tag' => '728x90_leaderboard',
58 'height' => '90',
59 'width' => '728',
60 ),
61 'mobile_leaderboard' => array(
62 'tag' => '320x50_mobileleaderboard',
63 'height' => '50',
64 'width' => '320',
65 ),
66 'wideskyscraper' => array(
67 'tag' => '160x600_wideskyscraper',
68 'height' => '600',
69 'width' => '160',
70 ),
71 );
72
73 /**
74 * Mapping array of location slugs to placement ids
75 *
76 * @var array
77 */
78 public static $ad_location_ids = array(
79 'top' => 110,
80 'belowpost' => 120,
81 'belowpost2' => 130,
82 'sidebar' => 140,
83 'widget' => 150,
84 'gutenberg' => 200,
85 'inline' => 310,
86 'inline-plugin' => 320,
87 );
88
89 /**
90 * Mapping array of form factor slugs to form factor ids
91 *
92 * @var array
93 */
94 public static $form_factor_ids = array(
95 'square' => '001', // 250x250
96 'leaderboard' => '002', // 728x90
97 'skyscraper' => '003', // 120x600
98 );
99
100 /**
101 * Counter to enable unique, sequential section IDs for all amp-ad units
102 *
103 * @var int
104 */
105 public static $amp_section_id = 1;
106
107 /**
108 * Solo unit CSS string.
109 *
110 * @var string
111 */
112 public static $solo_unit_css = 'float:left;margin-right:5px;margin-top:0px;';
113
114 /**
115 * Checks for AMP support and returns true iff active & AMP request
116 *
117 * @return boolean True if supported AMP request
118 *
119 * @since 7.5.0
120 */
121 public static function is_amp() {
122 return class_exists( 'Jetpack_AMP_Support' ) && Jetpack_AMP_Support::is_amp_request();
123 }
124
125 /**
126 * Increment the AMP section ID and return the value
127 *
128 * @return int
129 */
130 public static function get_amp_section_id() {
131 return self::$amp_section_id++;
132 }
133
134 /**
135 * Convenience function for grabbing options from params->options
136 *
137 * @param string $option the option to grab.
138 * @param mixed $default (optional).
139 * @return mixed option or $default if not set
140 *
141 * @since 4.5.0
142 */
143 public function option( $option, $default = false ) {
144 if ( ! isset( $this->params->options[ $option ] ) ) {
145 return $default;
146 }
147
148 return $this->params->options[ $option ];
149 }
150
151 /**
152 * Returns the ad tag property array for supported ad types.
153 *
154 * @return array array with ad tags
155 *
156 * @since 7.1.0
157 */
158 public function get_ad_tags() {
159 return self::$ad_tag_ids;
160 }
161
162 /**
163 * Returns the solo css for unit
164 *
165 * @return string the special css for solo units
166 *
167 * @since 7.1.0
168 */
169 public function get_solo_unit_css() {
170 return self::$solo_unit_css;
171 }
172
173 /**
174 * Instantiate the plugin
175 *
176 * @since 4.5.0
177 */
178 public function __construct() {
179 add_action( 'wp', array( $this, 'init' ) );
180 add_action( 'rest_api_init', array( $this, 'init' ) );
181 add_action( 'widgets_init', array( $this, 'widget_callback' ) );
182
183 if ( is_admin() ) {
184 WordAds_California_Privacy::init_ajax_actions();
185 WordAds_Consent_Management_Provider::init_ajax_actions();
186 }
187 }
188
189 /**
190 * Code to run on WordPress 'init' hook
191 *
192 * @since 4.5.0
193 */
194 public function init() {
195 require_once WORDADS_ROOT . '/php/class-wordads-params.php';
196 $this->params = new WordAds_Params();
197
198 if ( $this->should_bail() || self::is_infinite_scroll() ) {
199 return;
200 }
201
202 if ( is_admin() ) {
203 require_once WORDADS_ROOT . '/php/class-wordads-admin.php';
204 return;
205 }
206
207 $this->insert_adcode();
208
209 // Include California Privacy Act related features if enabled.
210 if ( $this->params->options['wordads_ccpa_enabled'] ) {
211 WordAds_California_Privacy::init();
212 }
213
214 // Initialize CMP if enabled.
215 if ( isset( $this->params->options['wordads_cmp_enabled'] ) && $this->params->options['wordads_cmp_enabled'] ) {
216 WordAds_Consent_Management_Provider::init();
217 }
218
219 // Initialize [wordads] shortcode.
220 WordAds_Shortcode::init();
221
222 // Initialize Smart.
223 WordAds_Smart::instance()->init( $this->params );
224
225 if ( ( isset( $_SERVER['REQUEST_URI'] ) && '/ads.txt' === $_SERVER['REQUEST_URI'] )
226 || ( site_url( 'ads.txt', 'relative' ) === $_SERVER['REQUEST_URI'] ) ) {
227
228 $ads_txt_transient = get_transient( 'wordads_ads_txt' );
229
230 if ( false === ( $ads_txt_transient ) ) {
231 $wordads_ads_txt = WordAds_API::get_wordads_ads_txt();
232 $ads_txt_transient = is_wp_error( $wordads_ads_txt ) ? '' : $wordads_ads_txt;
233 set_transient( 'wordads_ads_txt', $ads_txt_transient, DAY_IN_SECONDS );
234 }
235
236 /**
237 * Provide plugins a way of modifying the contents of the automatically-generated ads.txt file.
238 *
239 * @module wordads
240 *
241 * @since 6.1.0
242 *
243 * @param string WordAds_API::get_wordads_ads_txt() The contents of the ads.txt file.
244 */
245 $ads_txt_content = apply_filters( 'wordads_ads_txt', $ads_txt_transient );
246
247 http_response_code( 200 );
248 header( 'Content-Type: text/plain; charset=utf-8' );
249 echo esc_html( $ads_txt_content );
250 die( 0 );
251 }
252 }
253
254 /**
255 * Check for Jetpack's The_Neverending_Home_Page and use got_infinity
256 *
257 * @return boolean true if load came from infinite scroll
258 *
259 * @since 4.5.0
260 */
261 public static function is_infinite_scroll() {
262 return class_exists( 'The_Neverending_Home_Page' ) && The_Neverending_Home_Page::got_infinity();
263 }
264
265 /**
266 * Add the actions/filters to insert the ads. Checks for mobile or desktop.
267 *
268 * @since 4.5.0
269 */
270 private function insert_adcode() {
271 add_filter( 'wp_resource_hints', array( $this, 'resource_hints' ), 10, 2 );
272 add_action( 'wp_head', array( $this, 'insert_head_meta' ), 20 );
273 add_action( 'wp_head', array( $this, 'insert_head_iponweb' ), 30 );
274 add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
275 add_filter( 'wordads_ads_txt', array( $this, 'insert_custom_adstxt' ) );
276
277 /**
278 * Filters enabling ads in `the_content` filter
279 *
280 * @see https://jetpack.com/support/ads/
281 *
282 * @module wordads
283 *
284 * @since 5.8.0
285 *
286 * @param bool True to disable ads in `the_content`
287 */
288 if ( ! apply_filters( 'wordads_content_disable', false ) ) {
289 add_filter( 'the_content', array( $this, 'insert_ad' ) );
290 }
291
292 /**
293 * Filters enabling ads in `the_excerpt` filter
294 *
295 * @see https://jetpack.com/support/ads/
296 *
297 * @module wordads
298 *
299 * @since 5.8.0
300 *
301 * @param bool True to disable ads in `the_excerpt`
302 */
303 if ( ! apply_filters( 'wordads_excerpt_disable', false ) ) {
304 add_filter( 'the_excerpt', array( $this, 'insert_ad' ) );
305 }
306
307 if ( $this->option( 'enable_header_ad', true ) ) {
308 if ( self::is_amp() ) {
309 add_filter( 'the_content', array( $this, 'insert_header_ad_amp' ) );
310 } else {
311 add_action( 'wordads_header_ad', array( $this, 'insert_header_ad' ), 100 );
312 add_action( 'wp_footer', array( $this, 'insert_header_ad' ), 100 );
313 }
314 }
315 }
316
317 /**
318 * Register desktop scripts and styles
319 *
320 * @since 4.5.0
321 */
322 public function enqueue_scripts() {
323 wp_enqueue_style(
324 'wordads',
325 WORDADS_URL . 'css/style.css',
326 array(),
327 '2015-12-18'
328 );
329 }
330
331 /**
332 * Add the IPW resource hints
333 *
334 * @since 7.9
335 *
336 * @param array $hints Domains for hinting.
337 * @param string $relation_type Resource type.
338 *
339 * @return array Domains for hinting.
340 */
341 public function resource_hints( $hints, $relation_type ) {
342 if ( 'dns-prefetch' === $relation_type ) {
343 $hints[] = '//s.pubmine.com';
344 $hints[] = '//x.bidswitch.net';
345 $hints[] = '//static.criteo.net';
346 $hints[] = '//ib.adnxs.com';
347 $hints[] = '//aax.amazon-adsystem.com';
348 $hints[] = '//bidder.criteo.com';
349 $hints[] = '//cas.criteo.com';
350 $hints[] = '//gum.criteo.com';
351 $hints[] = '//ads.pubmatic.com';
352 $hints[] = '//gads.pubmatic.com';
353 $hints[] = '//tpc.googlesyndication.com';
354 $hints[] = '//ad.doubleclick.net';
355 $hints[] = '//googleads.g.doubleclick.net';
356 $hints[] = '//www.googletagservices.com';
357 $hints[] = '//cdn.switchadhub.com';
358 $hints[] = '//delivery.g.switchadhub.com';
359 $hints[] = '//delivery.swid.switchadhub.com';
360 }
361
362 return $hints;
363 }
364
365 /**
366 * IPONWEB metadata used by the various scripts
367 */
368 public function insert_head_meta() {
369 if ( self::is_amp() ) {
370 return;
371 }
372 $hosting_type = ( new Host() )->is_woa_site() ? 1 : 2; // 1 = WPCOM, 2 = Jetpack.
373 $pagetype = (int) $this->params->get_page_type_ipw();
374 $data_tags = ( $this->params->cloudflare ) ? ' data-cfasync="false"' : '';
375 $site_id = $this->params->blog_id;
376 $consent = (int) isset( $_COOKIE['personalized-ads-consent'] );
377 $is_logged_in = is_user_logged_in() ? '1' : '0';
378
379 $disabled_slot_formats = apply_filters( 'wordads_disabled_slot_formats', array() );
380
381 if ( apply_filters( 'wordads_iponweb_bottom_sticky_ad_disable', false ) ) {
382 $disabled_slot_formats[] = 'MTS';
383 }
384
385 if ( apply_filters( 'wordads_iponweb_sidebar_sticky_right_ad_disable', false ) ) {
386 $disabled_slot_formats[] = 'DPR';
387 }
388
389 $config = array(
390 'pt' => $pagetype,
391 'ht' => $hosting_type,
392 'tn' => get_stylesheet(),
393 'uloggedin' => $is_logged_in,
394 'amp' => false,
395 'siteid' => $site_id,
396 'consent' => $consent,
397 'ad' => array(
398 'label' => array(
399 'text' => __( 'Advertisements', 'jetpack' ),
400 ),
401 'reportAd' => array(
402 'text' => __( 'Report this ad', 'jetpack' ),
403 ),
404 'privacySettings' => array(
405 'text' => __( 'Privacy', 'jetpack' ),
406 'onClick' => 'js:function() { window.__tcfapi && window.__tcfapi(\'showUi\'); }',
407 ),
408 ),
409 'disabled_slot_formats' => $disabled_slot_formats,
410 );
411 $js_config = WordAds_Array_Utils::array_to_js_object( $config );
412 ?>
413 <script<?php echo esc_attr( $data_tags ); ?> type="text/javascript">
414 var __ATA_PP = <?php echo $js_config; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>;
415 var __ATA = __ATA || {};
416 __ATA.cmd = __ATA.cmd || [];
417 __ATA.criteo = __ATA.criteo || {};
418 __ATA.criteo.cmd = __ATA.criteo.cmd || [];
419 </script>
420 <?php
421
422 $section_id = $this->params->blog_id . 5;
423
424 // Get below post tag.
425 $tag_belowpost = $this->get_fallback_ad_snippet( $section_id, 'square', 'belowpost', '', '{{unique_id}}' );
426
427 // Remove linebreaks and sanitize.
428 $tag_belowpost = esc_js( str_replace( array( "\n", "\t", "\r" ), '', $tag_belowpost ) );
429
430 // Get an inline tag with a macro as id handled on JS side to use as a fallback.
431 $tag_inline = $this->get_fallback_ad_snippet( $section_id, 'square', 'inline', '', '{{unique_id}}' );
432
433 // Remove linebreaks and sanitize.
434 $tag_inline = esc_js( str_replace( array( "\n", "\t", "\r" ), '', $tag_inline ) );
435
436 // Get top tag.
437 $tag_top = $this->get_fallback_ad_snippet( $section_id, 'leaderboard', 'top', '', '{{unique_id}}' );
438
439 // Remove linebreaks and sanitize.
440 $tag_top = esc_js( str_replace( array( "\n", "\t", "\r" ), '', $tag_top ) );
441
442 // phpcs:disable WordPress.Security.EscapeOutput.HeredocOutputNotEscaped
443 echo <<<HTML
444 <script type="text/javascript">
445 var sas_fallback = sas_fallback || [];
446 sas_fallback.push(
447 { tag: "$tag_inline", type: 'inline' },
448 { tag: "$tag_belowpost", type: 'belowpost' },
449 { tag: "$tag_top", type: 'top' }
450 );
451 </script>
452 HTML;
453 }
454
455 /**
456 * IPONWEB scripts in <head>
457 *
458 * @since 4.5.0
459 */
460 public function insert_head_iponweb() {
461 if ( self::is_amp() ) {
462 return;
463 }
464
465 $data_tags = ( $this->params->cloudflare ) ? ' data-cfasync="false"' : '';
466 ?>
467 <script<?php echo esc_attr( $data_tags ); ?> type="text/javascript">
468 (function(){var g=Date.now||function(){return+new Date};function h(a,b){a:{for(var c=a.length,d="string"==typeof a?a.split(""):a,e=0;e<c;e++)if(e in d&&b.call(void 0,d[e],e,a)){b=e;break a}b=-1}return 0>b?null:"string"==typeof a?a.charAt(b):a[b]};function k(a,b,c){c=null!=c?"="+encodeURIComponent(String(c)):"";if(b+=c){c=a.indexOf("#");0>c&&(c=a.length);var d=a.indexOf("?");if(0>d||d>c){d=c;var e=""}else e=a.substring(d+1,c);a=[a.substr(0,d),e,a.substr(c)];c=a[1];a[1]=b?c?c+"&"+b:b:c;a=a[0]+(a[1]?"?"+a[1]:"")+a[2]}return a};var l=0;function m(a,b){var c=document.createElement("script");c.src=a;c.onload=function(){b&&b(void 0)};c.onerror=function(){b&&b("error")};a=document.getElementsByTagName("head");var d;a&&0!==a.length?d=a[0]:d=document.documentElement;d.appendChild(c)}function n(a){var b=void 0===b?document.cookie:b;return(b=h(b.split("; "),function(c){return-1!=c.indexOf(a+"=")}))?b.split("=")[1]:""}function p(a){return"string"==typeof a&&0<a.length}
469 function r(a,b,c){b=void 0===b?"":b;c=void 0===c?".":c;var d=[];Object.keys(a).forEach(function(e){var f=a[e],q=typeof f;"object"==q&&null!=f||"function"==q?d.push(r(f,b+e+c)):null!==f&&void 0!==f&&(e=encodeURIComponent(b+e),d.push(e+"="+encodeURIComponent(f)))});return d.filter(p).join("&")}function t(a,b){a||((window.__ATA||{}).config=b.c,m(b.url))}var u=Math.floor(1E13*Math.random()),v=window.__ATA||{};window.__ATA=v;window.__ATA.cmd=v.cmd||[];v.rid=u;v.createdAt=g();var w=window.__ATA||{},x="s.pubmine.com";
470 w&&w.serverDomain&&(x=w.serverDomain);var y="//"+x+"/conf",z=window.top===window,A=window.__ATA_PP&&window.__ATA_PP.gdpr_applies,B="boolean"===typeof A?Number(A):null,C=window.__ATA_PP||null,D=z?document.referrer?document.referrer:null:null,E=z?window.location.href:document.referrer?document.referrer:null,F,G=n("__ATA_tuuid");F=G?G:null;var H=window.innerWidth+"x"+window.innerHeight,I=n("usprivacy"),J=r({gdpr:B,pp:C,rid:u,src:D,ref:E,tuuid:F,vp:H,us_privacy:I?I:null},"",".");
471 (function(a){var b=void 0===b?"cb":b;l++;var c="callback__"+g().toString(36)+"_"+l.toString(36);a=k(a,b,c);window[c]=function(d){t(void 0,d)};m(a,function(d){d&&t(d)})})(y+"?"+J);}).call(this);
472 </script>
473 <?php
474 }
475
476 /**
477 * Insert the ad onto the page
478 *
479 * @since 4.5.0
480 *
481 * @param string $content HTML content.
482 */
483 public function insert_ad( $content ) {
484 // Don't insert ads in feeds, or for anything but the main display. (This is required for compatibility with the Publicize module).
485 if ( is_feed() || ! is_main_query() || ! in_the_loop() ) {
486 return $content;
487 }
488 /**
489 * Allow third-party tools to disable the display of in post ads.
490 *
491 * @module wordads
492 *
493 * @since 4.5.0
494 *
495 * @param bool true Should the in post unit be disabled. Default to false.
496 */
497 $disable = apply_filters( 'wordads_inpost_disable', false );
498 if ( ! $this->params->should_show() || $disable ) {
499 return $content;
500 }
501
502 $ad_type = $this->option( 'wordads_house' ) ? 'house' : 'iponweb';
503 return $content . $this->get_ad( 'belowpost', $ad_type );
504 }
505
506 /**
507 * Insert an inline ad into a post content
508 * Used for rendering the `wordads` shortcode.
509 *
510 * @since 6.1.0
511 *
512 * @param string $content HTML content.
513 */
514 public function insert_inline_ad( $content ) {
515 // Ad JS won't work in XML feeds.
516 if ( is_feed() ) {
517 return $content;
518 }
519 /**
520 * Allow third-party tools to disable the display of in post ads.
521 *
522 * @module wordads
523 *
524 * @since 4.5.0
525 *
526 * @param bool true Should the in post unit be disabled. Default to false.
527 */
528 $disable = apply_filters( 'wordads_inpost_disable', false );
529 if ( $disable ) {
530 return $content;
531 }
532
533 $ad_type = $this->option( 'wordads_house' ) ? 'house' : 'iponweb';
534 $location = 'shortcode';
535
536 // Not house ad and WATL enabled.
537 // phpcs:disable WordPress.Security.NonceVerification.Recommended
538 if ( 'house' !== $ad_type && ( isset( $_GET['wordads-logging'] ) && isset( $_GET[ $location ] ) && 'true' === $_GET[ $location ] ) ) {
539 return $content . $this->get_watl_ad_html_tag( $location );
540 }
541
542 return $content . $this->get_ad( 'inline', $ad_type );
543 }
544
545 /**
546 * Inserts ad into header
547 *
548 * @since 4.5.0
549 */
550 public function insert_header_ad() {
551 /**
552 * Allow third-party tools to disable the display of header ads.
553 *
554 * @module wordads
555 *
556 * @since 4.5.0
557 *
558 * @param bool true Should the header unit be disabled. Default to false.
559 */
560 if ( apply_filters( 'wordads_header_disable', false ) ) {
561 return;
562 }
563
564 // Prevent multiple manual ads.
565 if ( 2 <= did_action( 'wordads_header_ad' ) ) {
566 return;
567 }
568
569 // Prevent placing an automatic ad if a manual ad has already been placed.
570 if ( doing_action( 'wp_footer' ) && did_action( 'wordads_header_ad' ) ) {
571 return;
572 }
573
574 // Prevent placing a manual ad if an automatic ad has already been placed.
575 if ( doing_action( 'wordads_header_ad' ) && did_action( 'wp_footer' ) ) {
576 return;
577 }
578
579 // Default ad placement to just after the <body> tag.
580 $selector = 'body > :first-child';
581
582 // Special theme cases.
583 switch ( get_stylesheet() ) {
584 case 'twentyseventeen':
585 $selector = '#content';
586 break;
587 case 'twentyfifteen':
588 $selector = '#main';
589 break;
590 case 'twentyfourteen':
591 $selector = 'article';
592 break;
593 }
594
595 // Don't relocate if the ad is being placed manually.
596 if ( doing_action( 'wordads_header_ad' ) ) {
597 $selector = '';
598 }
599
600 $section_id = 0 === $this->params->blog_id ? WORDADS_API_TEST_ID : $this->params->blog_id . '2';
601 $form_factor = $this->params->mobile_device ? 'square' : 'leaderboard';
602 echo $this->get_dynamic_ad_snippet( $section_id, $form_factor, 'top', $selector ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
603 }
604
605 /**
606 * Header unit for AMP
607 *
608 * @param string $content Content of the page.
609 *
610 * @since 7.5.0
611 */
612 public function insert_header_ad_amp( $content ) {
613
614 $ad_type = $this->option( 'wordads_house' ) ? 'house' : 'iponweb';
615 if ( 'house' === $ad_type ) {
616 return $content;
617 }
618 return $this->get_ad( 'top_amp', $ad_type ) . $content;
619 }
620
621 /**
622 * Filter the latest ads.txt to include custom user entries. Strips any tags or whitespace.
623 *
624 * @param string $adstxt The ads.txt being filtered.
625 * @return string Filtered ads.txt with custom entries, if applicable.
626 *
627 * @since 6.5.0
628 */
629 public function insert_custom_adstxt( $adstxt ) {
630 if ( ! $this->option( 'wordads_custom_adstxt_enabled' ) ) {
631 return $adstxt;
632 }
633
634 $custom_adstxt = trim( wp_strip_all_tags( $this->option( 'wordads_custom_adstxt' ) ) );
635 if ( $custom_adstxt ) {
636 $adstxt .= "\n\n#Jetpack - User Custom Entries\n";
637 $adstxt .= $custom_adstxt . "\n";
638 }
639
640 return $adstxt;
641 }
642
643 /**
644 * Get the ad for the spot and type.
645 *
646 * @param string $spot top, side, inline, or belowpost.
647 * @param string $type iponweb or adsense.
648 */
649 public function get_ad( $spot, $type = 'iponweb' ) {
650 $snippet = '';
651 if ( 'iponweb' === $type ) {
652 $section_id = WORDADS_API_TEST_ID;
653 $snippet = '';
654
655 if ( 'top' === $spot ) {
656 // mrec for mobile, leaderboard for desktop.
657 $section_id = 0 === $this->params->blog_id ? WORDADS_API_TEST_ID : $this->params->blog_id . '2';
658 $form_factor = $this->params->mobile_device ? 'square' : 'leaderboard';
659 $snippet = $this->get_dynamic_ad_snippet( $section_id, $form_factor, $spot );
660 } elseif ( 'belowpost' === $spot ) {
661 $section_id = 0 === $this->params->blog_id ? WORDADS_API_TEST_ID : $this->params->blog_id . '1';
662 $snippet = $this->get_dynamic_ad_snippet( $section_id, 'square', $spot );
663 } elseif ( 'inline' === $spot ) {
664 $section_id = 0 === $this->params->blog_id ? WORDADS_API_TEST_ID : $this->params->blog_id . '5';
665 $snippet = $this->get_dynamic_ad_snippet( $section_id, 'square', $spot );
666 } elseif ( 'top_amp' === $spot ) {
667 // Ad unit which can safely be inserted below title, above content in a variety of themes.
668 $width = 300;
669 $height = 250;
670 $snippet = $this->get_ad_div( $spot, $this->get_amp_snippet( $height, $width ) );
671 }
672 } elseif ( 'house' === $type ) {
673 $leaderboard = 'top' === $spot && ! $this->params->mobile_device;
674 $snippet = $this->get_house_ad( $leaderboard ? 'leaderboard' : 'mrec' );
675 if ( 'belowpost' === $spot && $this->option( 'wordads_second_belowpost', true ) ) {
676 $snippet .= $this->get_house_ad( $leaderboard ? 'leaderboard' : 'mrec' );
677 }
678 }
679
680 return $snippet;
681 }
682
683 /**
684 * Returns the AMP snippet to be inserted
685 *
686 * @param int $height Height.
687 * @param int $width Width.
688 * @return string
689 *
690 * @since 8.7
691 */
692 public function get_amp_snippet( $height, $width ) {
693 $height = esc_attr( $height + 15 ); // this will ensure enough padding for "Report this ad".
694 $width = esc_attr( $width );
695 $amp_section_id = esc_attr( self::get_amp_section_id() );
696 $site_id = esc_attr( $this->params->blog_id );
697 return <<<HTML
698 <amp-ad width="$width" height="$height"
699 type="pubmine"
700 data-siteid="$site_id"
701 data-section="$amp_section_id">
702 </amp-ad>
703 HTML;
704 }
705
706 /**
707 * Compatibility function -- main functionality replaced with get_dynamic_ad_snippet
708 *
709 * @param int $section_id Ad section.
710 * @param int $height Ad height.
711 * @param int $width Ad width.
712 * @param string $location Location.
713 * @param string $css CSS.
714 *
715 * @return string
716 *
717 * @since 5.7
718 */
719 public function get_ad_snippet( $section_id, $height, $width, $location = '', $css = '' ) {
720 if ( class_exists( 'Jetpack_AMP_Support' ) && Jetpack_AMP_Support::is_amp_request() ) {
721 return $this->get_amp_snippet( $height, $width );
722 }
723
724 $this->ads[] = array(
725 'location' => $location,
726 'width' => $width,
727 'height' => $height,
728 );
729
730 if ( 'gutenberg' === $location ) {
731 $ad_number = count( $this->ads ) . '-' . uniqid();
732 $data_tags = $this->params->cloudflare ? ' data-cfasync="false"' : '';
733 $css = esc_attr( $css );
734
735 $loc_id = 100;
736 if ( ! empty( self::$ad_location_ids[ $location ] ) ) {
737 $loc_id = self::$ad_location_ids[ $location ];
738 }
739
740 $loc_id = esc_js( $loc_id );
741 return <<<HTML
742 <div style="padding-bottom:15px;width:{$width}px;height:{$height}px;$css">
743 <div id="atatags-{$ad_number}">
744 <script$data_tags type="text/javascript">
745 __ATA.cmd.push(function() {
746 __ATA.initSlot('atatags-{$ad_number}', {
747 collapseEmpty: 'before',
748 sectionId: '{$section_id}',
749 location: {$loc_id},
750 width: {$width},
751 height: {$height}
752 });
753 });
754 </script>
755 </div>
756 </div>
757 HTML;
758 }
759
760 $form_factor = 'square';
761 if ( 250 > $width ) {
762 $form_factor = 'skyscraper';
763 } elseif ( 300 < $width ) {
764 $form_factor = 'leaderboard';
765 }
766
767 return $this->get_dynamic_ad_snippet( $section_id, $form_factor, $location );
768 }
769
770 /**
771 * Returns the dynamic snippet to be inserted into the ad unit
772 *
773 * @param int $section_id section_id.
774 * @param string $form_factor form_factor.
775 * @param string $location location.
776 * @param string $relocate location to be moved after the fact for themes without required hook.
777 * @param string | null $id A unique string ID or placeholder.
778 *
779 * @return string
780 *
781 * @since 8.7
782 */
783 public function get_dynamic_ad_snippet( $section_id, $form_factor = 'square', $location = '', $relocate = '', $id = null ) {
784
785 // Allow overriding and printing of the tag parsed by the WATL.
786 // phpcs:disable WordPress.Security.NonceVerification.Recommended
787 $is_location_enabled = isset( $_GET['wordads-logging'] ) && isset( $_GET[ $location ] ) && 'true' === $_GET[ $location ];
788
789 if ( ( 'top' === $location || 'belowpost' === $location ) && $is_location_enabled ) {
790 return self::get_watl_ad_html_tag( $location );
791 }
792
793 return $this->get_fallback_ad_snippet( $section_id, $form_factor, $location, $relocate, $id );
794 }
795
796 /**
797 * Returns the fallback dynamic snippet to be inserted into the ad unit
798 *
799 * @param int $section_id section_id.
800 * @param string $form_factor form_factor.
801 * @param string $location location.
802 * @param string $relocate location to be moved after the fact for themes without required hook.
803 * @param string | null $id A unique string ID or placeholder.
804 *
805 * @return string
806 *
807 * @since 8.7
808 */
809 public function get_fallback_ad_snippet( $section_id, $form_factor = 'square', $location = '', $relocate = '', $id = null ) {
810 $div_id = 'atatags-' . $section_id . '-' . ( $id ?? uniqid() );
811 $div_id = esc_attr( $div_id );
812
813 // Default form factor.
814 $form_factor_id = self::$form_factor_ids['square'];
815 if ( isset( self::$form_factor_ids[ $form_factor ] ) ) {
816 $form_factor_id = self::$form_factor_ids[ $form_factor ];
817 }
818
819 $loc_id = 100;
820 if ( isset( self::$ad_location_ids[ $location ] ) ) {
821 $loc_id = self::$ad_location_ids[ $location ];
822 }
823
824 $form_factor_id = esc_js( $form_factor_id );
825 $advertisements_text = esc_js( __( 'Advertisements', 'jetpack' ) );
826 $report_ad_text = esc_js( __( 'Report this ad', 'jetpack' ) );
827 $privacy_settings_text = esc_js( __( 'Privacy settings', 'jetpack' ) );
828
829 $relocate_script = '';
830 if ( ! empty( $relocate ) ) {
831 $selector = wp_json_encode( $relocate );
832 $relocate_script = <<<JS
833 <script type="text/javascript">
834 var adNode = document.getElementById( '{$div_id}' );
835 var selector = {$selector};
836 var relocateNode = document.querySelector( selector );
837 relocateNode.parentNode.insertBefore( adNode, relocateNode );
838 </script>
839 JS;
840 }
841
842 return <<<HTML
843 <div id="{$div_id}"></div>
844 {$relocate_script}
845 <script>
846 __ATA.cmd.push(function() {
847 __ATA.initDynamicSlot({
848 id: '{$div_id}',
849 location: {$loc_id},
850 formFactor: '{$form_factor_id}',
851 label: {
852 text: '{$advertisements_text}',
853 },
854 creative: {
855 reportAd: {
856 text: '{$report_ad_text}',
857 },
858 privacySettings: {
859 text: '{$privacy_settings_text}',
860 onClick: function() { window.__tcfapi && window.__tcfapi('showUi'); },
861 }
862 }
863 });
864 });
865 </script>
866 HTML;
867 }
868
869 /**
870 * Returns the complete ad div with snippet to be inserted into the page
871 *
872 * @param string $spot top, side, inline, or belowpost.
873 * @param string $snippet The snippet to insert into the div.
874 * @param array $css_classes CSS classes.
875 * @return string The supporting ad unit div.
876 *
877 * @since 7.1
878 */
879 public function get_ad_div( $spot, $snippet, array $css_classes = array() ) {
880 if ( strpos( strtolower( $spot ), 'amp' ) === false && ! 'inline' === $spot ) {
881 return $snippet; // we don't want dynamic ads to be inserted for AMP & Gutenberg.
882 }
883
884 if ( empty( $css_classes ) ) {
885 $css_classes = array();
886 }
887
888 $css_classes[] = 'wpcnt';
889 if ( 'top' === $spot ) {
890 $css_classes[] = 'wpcnt-header';
891 }
892
893 $spot = esc_attr( $spot );
894 $classes = esc_attr( implode( ' ', $css_classes ) );
895 $about = esc_html__( 'Advertisements', 'jetpack' );
896 return <<<HTML
897 <div class="$classes">
898 <div class="wpa">
899 <span class="wpa-about">$about</span>
900 <div class="u $spot">
901 $snippet
902 </div>
903 </div>
904 </div>
905 HTML;
906 }
907
908 /**
909 * Check the reasons to bail before we attempt to insert ads.
910 *
911 * @return true if we should bail (don't insert ads)
912 *
913 * @since 4.5.0
914 */
915 public function should_bail() {
916 return ! $this->option( 'wordads_approved' ) || (bool) $this->option( 'wordads_unsafe' );
917 }
918
919 /**
920 * Returns markup for HTML5 house ad base on unit
921 *
922 * @param string $unit mrec, widesky, or leaderboard.
923 * @return string markup for HTML5 house ad
924 *
925 * @since 4.7.0
926 */
927 public function get_house_ad( $unit = 'mrec' ) {
928
929 switch ( $unit ) {
930 case 'widesky':
931 $width = 160;
932 $height = 600;
933 break;
934 case 'leaderboard':
935 $width = 728;
936 $height = 90;
937 break;
938 case 'mrec':
939 default:
940 $width = 300;
941 $height = 250;
942 break;
943 }
944
945 return <<<HTML
946 <iframe
947 src="https://s0.wp.com/wp-content/blog-plugins/wordads/house/html5/$unit/index.html"
948 width="$width"
949 height="$height"
950 frameborder="0"
951 scrolling="no"
952 marginheight="0"
953 marginwidth="0">
954 </iframe>
955 HTML;
956 }
957
958 /**
959 * Returns the html ad tag used by WordAds Tag Library
960 *
961 * @param string $slot_type e.g belowpost, gutenberg_rectangle.
962 *
963 * @return string
964 *
965 * @since 8.7
966 */
967 public static function get_watl_ad_html_tag( string $slot_type ): string {
968 return "<div class=\"wordads-tag\" data-slot-type=\"$slot_type\" style=\"display: none;\"></div>";
969 }
970
971 /**
972 * Activation hook actions
973 *
974 * @since 4.5.0
975 */
976 public static function activate() {
977 WordAds_API::update_wordads_status_from_api();
978 }
979
980 /**
981 * Registers the widgets.
982 */
983 public function widget_callback() {
984 register_widget( 'WordAds_Sidebar_Widget' );
985
986 $ccpa_enabled = get_option( 'wordads_ccpa_enabled' );
987
988 if ( $ccpa_enabled ) {
989 register_widget( 'WordAds_Ccpa_Do_Not_Sell_Link_Widget' );
990 }
991 }
992 }
993
994 add_action( 'jetpack_activate_module_wordads', array( 'WordAds', 'activate' ) );
995 add_action( 'jetpack_activate_module_wordads', array( 'WordAds_Cron', 'activate' ) );
996 add_action( 'jetpack_deactivate_module_wordads', array( 'WordAds_Cron', 'deactivate' ) );
997
998 global $wordads;
999 $wordads = new WordAds();
1000