PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 13.2.4
Jetpack – WP Security, Backup, Speed, & Growth v13.2.4
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 2 years ago php 2 years ago class-wordads.php 2 years ago
class-wordads.php
879 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
24 /**
25 * Primary WordAds class.
26 */
27 class WordAds {
28
29 /**
30 * Ads parameters.
31 *
32 * @var null
33 */
34 public $params = null;
35
36 /**
37 * Ads.
38 *
39 * @var array
40 */
41 public $ads = array();
42
43 /**
44 * Array of supported ad types.
45 *
46 * @var array
47 */
48 public static $ad_tag_ids = array(
49 'mrec' => array(
50 'tag' => '300x250_mediumrectangle',
51 'height' => '250',
52 'width' => '300',
53 ),
54 'leaderboard' => array(
55 'tag' => '728x90_leaderboard',
56 'height' => '90',
57 'width' => '728',
58 ),
59 'mobile_leaderboard' => array(
60 'tag' => '320x50_mobileleaderboard',
61 'height' => '50',
62 'width' => '320',
63 ),
64 'wideskyscraper' => array(
65 'tag' => '160x600_wideskyscraper',
66 'height' => '600',
67 'width' => '160',
68 ),
69 );
70
71 /**
72 * Mapping array of location slugs to placement ids
73 *
74 * @var array
75 */
76 public static $ad_location_ids = array(
77 'top' => 110,
78 'belowpost' => 120,
79 'belowpost2' => 130,
80 'sidebar' => 140,
81 'widget' => 150,
82 'gutenberg' => 200,
83 'inline' => 310,
84 'inline-plugin' => 320,
85 );
86
87 /**
88 * Mapping array of form factor slugs to form factor ids
89 *
90 * @var array
91 */
92 public static $form_factor_ids = array(
93 'square' => '001', // 250x250
94 'leaderboard' => '002', // 728x90
95 'skyscraper' => '003', // 120x600
96 );
97
98 /**
99 * Counter to enable unique, sequential section IDs for all amp-ad units
100 *
101 * @var int
102 */
103 public static $amp_section_id = 1;
104
105 /**
106 * Solo unit CSS string.
107 *
108 * @var string
109 */
110 public static $solo_unit_css = 'float:left;margin-right:5px;margin-top:0px;';
111
112 /**
113 * Checks for AMP support and returns true iff active & AMP request
114 *
115 * @return boolean True if supported AMP request
116 *
117 * @since 7.5.0
118 */
119 public static function is_amp() {
120 return class_exists( 'Jetpack_AMP_Support' ) && Jetpack_AMP_Support::is_amp_request();
121 }
122
123 /**
124 * Increment the AMP section ID and return the value
125 *
126 * @return int
127 */
128 public static function get_amp_section_id() {
129 return self::$amp_section_id++;
130 }
131
132 /**
133 * Convenience function for grabbing options from params->options
134 *
135 * @param string $option the option to grab.
136 * @param mixed $default (optional).
137 * @return option or $default if not set
138 *
139 * @since 4.5.0
140 */
141 public function option( $option, $default = false ) {
142 if ( ! isset( $this->params->options[ $option ] ) ) {
143 return $default;
144 }
145
146 return $this->params->options[ $option ];
147 }
148
149 /**
150 * Returns the ad tag property array for supported ad types.
151 *
152 * @return array array with ad tags
153 *
154 * @since 7.1.0
155 */
156 public function get_ad_tags() {
157 return self::$ad_tag_ids;
158 }
159
160 /**
161 * Returns the solo css for unit
162 *
163 * @return string the special css for solo units
164 *
165 * @since 7.1.0
166 */
167 public function get_solo_unit_css() {
168 return self::$solo_unit_css;
169 }
170
171 /**
172 * Instantiate the plugin
173 *
174 * @since 4.5.0
175 */
176 public function __construct() {
177 add_action( 'wp', array( $this, 'init' ) );
178 add_action( 'rest_api_init', array( $this, 'init' ) );
179 add_action( 'widgets_init', array( $this, 'widget_callback' ) );
180
181 if ( is_admin() ) {
182 WordAds_California_Privacy::init_ajax_actions();
183 WordAds_Consent_Management_Provider::init_ajax_actions();
184 }
185 }
186
187 /**
188 * Code to run on WordPress 'init' hook
189 *
190 * @since 4.5.0
191 */
192 public function init() {
193 require_once WORDADS_ROOT . '/php/class-wordads-params.php';
194 $this->params = new WordAds_Params();
195
196 if ( $this->should_bail() || self::is_infinite_scroll() ) {
197 return;
198 }
199
200 if ( is_admin() ) {
201 require_once WORDADS_ROOT . '/php/class-wordads-admin.php';
202 return;
203 }
204
205 $this->insert_adcode();
206
207 // Include California Privacy Act related features if enabled.
208 if ( $this->params->options['wordads_ccpa_enabled'] ) {
209 WordAds_California_Privacy::init();
210 }
211
212 // Initialize CMP if enabled.
213 if ( isset( $this->params->options['wordads_cmp_enabled'] ) && $this->params->options['wordads_cmp_enabled'] ) {
214 WordAds_Consent_Management_Provider::init();
215 }
216
217 if ( isset( $_SERVER['REQUEST_URI'] ) && '/ads.txt' === $_SERVER['REQUEST_URI'] ) {
218
219 $ads_txt_transient = get_transient( 'wordads_ads_txt' );
220
221 if ( false === ( $ads_txt_transient ) ) {
222 $wordads_ads_txt = WordAds_API::get_wordads_ads_txt();
223 $ads_txt_transient = is_wp_error( $wordads_ads_txt ) ? '' : $wordads_ads_txt;
224 set_transient( 'wordads_ads_txt', $ads_txt_transient, DAY_IN_SECONDS );
225 }
226
227 /**
228 * Provide plugins a way of modifying the contents of the automatically-generated ads.txt file.
229 *
230 * @module wordads
231 *
232 * @since 6.1.0
233 *
234 * @param string WordAds_API::get_wordads_ads_txt() The contents of the ads.txt file.
235 */
236 $ads_txt_content = apply_filters( 'wordads_ads_txt', $ads_txt_transient );
237
238 http_response_code( 200 );
239 header( 'Content-Type: text/plain; charset=utf-8' );
240 echo esc_html( $ads_txt_content );
241 die();
242 }
243 }
244
245 /**
246 * Check for Jetpack's The_Neverending_Home_Page and use got_infinity
247 *
248 * @return boolean true if load came from infinite scroll
249 *
250 * @since 4.5.0
251 */
252 public static function is_infinite_scroll() {
253 return class_exists( 'The_Neverending_Home_Page' ) && The_Neverending_Home_Page::got_infinity();
254 }
255
256 /**
257 * Add the actions/filters to insert the ads. Checks for mobile or desktop.
258 *
259 * @since 4.5.0
260 */
261 private function insert_adcode() {
262 add_filter( 'wp_resource_hints', array( $this, 'resource_hints' ), 10, 2 );
263 add_action( 'wp_head', array( $this, 'insert_head_meta' ), 20 );
264 add_action( 'wp_head', array( $this, 'insert_head_iponweb' ), 30 );
265 add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
266 add_filter( 'wordads_ads_txt', array( $this, 'insert_custom_adstxt' ) );
267
268 /**
269 * Filters enabling ads in `the_content` filter
270 *
271 * @see https://jetpack.com/support/ads/
272 *
273 * @module wordads
274 *
275 * @since 5.8.0
276 *
277 * @param bool True to disable ads in `the_content`
278 */
279 if ( ! apply_filters( 'wordads_content_disable', false ) ) {
280 add_filter( 'the_content', array( $this, 'insert_ad' ) );
281 }
282
283 /**
284 * Filters enabling ads in `the_excerpt` filter
285 *
286 * @see https://jetpack.com/support/ads/
287 *
288 * @module wordads
289 *
290 * @since 5.8.0
291 *
292 * @param bool True to disable ads in `the_excerpt`
293 */
294 if ( ! apply_filters( 'wordads_excerpt_disable', false ) ) {
295 add_filter( 'the_excerpt', array( $this, 'insert_ad' ) );
296 }
297
298 if ( $this->option( 'enable_header_ad', true ) ) {
299 if ( self::is_amp() ) {
300 add_filter( 'the_content', array( $this, 'insert_header_ad_amp' ) );
301 } else {
302 add_action( 'wordads_header_ad', array( $this, 'insert_header_ad' ), 100 );
303 add_action( 'wp_footer', array( $this, 'insert_header_ad' ), 100 );
304 }
305 }
306 }
307
308 /**
309 * Register desktop scripts and styles
310 *
311 * @since 4.5.0
312 */
313 public function enqueue_scripts() {
314 wp_enqueue_style(
315 'wordads',
316 WORDADS_URL . 'css/style.css',
317 array(),
318 '2015-12-18'
319 );
320 }
321
322 /**
323 * Add the IPW resource hints
324 *
325 * @since 7.9
326 *
327 * @param array $hints Domains for hinting.
328 * @param string $relation_type Resource type.
329 *
330 * @return array Domains for hinting.
331 */
332 public function resource_hints( $hints, $relation_type ) {
333 if ( 'dns-prefetch' === $relation_type ) {
334 $hints[] = '//s.pubmine.com';
335 $hints[] = '//x.bidswitch.net';
336 $hints[] = '//static.criteo.net';
337 $hints[] = '//ib.adnxs.com';
338 $hints[] = '//aax.amazon-adsystem.com';
339 $hints[] = '//bidder.criteo.com';
340 $hints[] = '//cas.criteo.com';
341 $hints[] = '//gum.criteo.com';
342 $hints[] = '//ads.pubmatic.com';
343 $hints[] = '//gads.pubmatic.com';
344 $hints[] = '//tpc.googlesyndication.com';
345 $hints[] = '//ad.doubleclick.net';
346 $hints[] = '//googleads.g.doubleclick.net';
347 $hints[] = '//www.googletagservices.com';
348 $hints[] = '//cdn.switchadhub.com';
349 $hints[] = '//delivery.g.switchadhub.com';
350 $hints[] = '//delivery.swid.switchadhub.com';
351 }
352
353 return $hints;
354 }
355
356 /**
357 * IPONWEB metadata used by the various scripts
358 *
359 * @return [type] [description]
360 */
361 public function insert_head_meta() {
362 if ( self::is_amp() ) {
363 return;
364 }
365 $hosting_type = ( new Host() )->is_woa_site() ? 1 : 2; // 1 = WPCOM, 2 = Jetpack.
366 $pagetype = (int) $this->params->get_page_type_ipw();
367 $data_tags = ( $this->params->cloudflare ) ? ' data-cfasync="false"' : '';
368 $site_id = $this->params->blog_id;
369 $consent = (int) isset( $_COOKIE['personalized-ads-consent'] );
370 $is_logged_in = is_user_logged_in() ? '1' : '0';
371 ?>
372 <script<?php echo esc_attr( $data_tags ); ?> type="text/javascript">
373 var __ATA_PP = { pt: <?php echo esc_js( $pagetype ); ?>, ht: <?php echo esc_js( $hosting_type ); ?>, tn: '<?php echo esc_js( get_stylesheet() ); ?>', uloggedin: <?php echo esc_js( $is_logged_in ); ?>, amp: false, siteid: <?php echo esc_js( $site_id ); ?>, consent: <?php echo esc_js( $consent ); ?>, ad: { label: { text: '<?php echo esc_js( __( 'Advertisements', 'jetpack' ) ); ?>' }, reportAd: { text: '<?php echo esc_js( __( 'Report this ad', 'jetpack' ) ); ?>' }, privacySettings: { text: '<?php echo esc_js( __( 'Privacy', 'jetpack' ) ); ?>', onClick: function() { window.__tcfapi && window.__tcfapi('showUi'); } } } };
374 var __ATA = __ATA || {};
375 __ATA.cmd = __ATA.cmd || [];
376 __ATA.criteo = __ATA.criteo || {};
377 __ATA.criteo.cmd = __ATA.criteo.cmd || [];
378 </script>
379 <?php
380 }
381
382 /**
383 * IPONWEB scripts in <head>
384 *
385 * @since 4.5.0
386 */
387 public function insert_head_iponweb() {
388 if ( self::is_amp() ) {
389 return;
390 }
391
392 $data_tags = ( $this->params->cloudflare ) ? ' data-cfasync="false"' : '';
393 ?>
394 <script<?php echo esc_attr( $data_tags ); ?> type="text/javascript">
395 (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}
396 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";
397 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},"",".");
398 (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);
399 </script>
400 <?php
401 }
402
403 /**
404 * Insert the ad onto the page
405 *
406 * @since 4.5.0
407 *
408 * @param string $content HTML content.
409 */
410 public function insert_ad( $content ) {
411 // Don't insert ads in feeds, or for anything but the main display. (This is required for compatibility with the Publicize module).
412 if ( is_feed() || ! is_main_query() || ! in_the_loop() ) {
413 return $content;
414 }
415 /**
416 * Allow third-party tools to disable the display of in post ads.
417 *
418 * @module wordads
419 *
420 * @since 4.5.0
421 *
422 * @param bool true Should the in post unit be disabled. Default to false.
423 */
424 $disable = apply_filters( 'wordads_inpost_disable', false );
425 if ( ! $this->params->should_show() || $disable ) {
426 return $content;
427 }
428
429 $ad_type = $this->option( 'wordads_house' ) ? 'house' : 'iponweb';
430 return $content . $this->get_ad( 'belowpost', $ad_type );
431 }
432
433 /**
434 * Insert an inline ad into a post content
435 * Used for rendering the `wordads` shortcode.
436 *
437 * @since 6.1.0
438 *
439 * @param string $content HTML content.
440 */
441 public function insert_inline_ad( $content ) {
442 // Ad JS won't work in XML feeds.
443 if ( is_feed() ) {
444 return $content;
445 }
446 /**
447 * Allow third-party tools to disable the display of in post ads.
448 *
449 * @module wordads
450 *
451 * @since 4.5.0
452 *
453 * @param bool true Should the in post unit be disabled. Default to false.
454 */
455 $disable = apply_filters( 'wordads_inpost_disable', false );
456 if ( $disable ) {
457 return $content;
458 }
459
460 $ad_type = $this->option( 'wordads_house' ) ? 'house' : 'iponweb';
461 $content .= $this->get_ad( 'inline', $ad_type );
462 return $content;
463 }
464
465 /**
466 * Inserts ad into header
467 *
468 * @since 4.5.0
469 */
470 public function insert_header_ad() {
471 /**
472 * Allow third-party tools to disable the display of header ads.
473 *
474 * @module wordads
475 *
476 * @since 4.5.0
477 *
478 * @param bool true Should the header unit be disabled. Default to false.
479 */
480 if ( apply_filters( 'wordads_header_disable', false ) ) {
481 return;
482 }
483
484 // Prevent multiple manual ads.
485 if ( 2 <= did_action( 'wordads_header_ad' ) ) {
486 return;
487 }
488
489 // Prevent placing an automatic ad if a manual ad has already been placed.
490 if ( doing_action( 'wp_footer' ) && did_action( 'wordads_header_ad' ) ) {
491 return;
492 }
493
494 // Prevent placing a manual ad if an automatic ad has already been placed.
495 if ( doing_action( 'wordads_header_ad' ) && did_action( 'wp_footer' ) ) {
496 return;
497 }
498
499 // Default ad placement to just after the <body> tag.
500 $selector = 'body > :first-child';
501
502 // Special theme cases.
503 switch ( get_stylesheet() ) {
504 case 'twentyseventeen':
505 $selector = '#content';
506 break;
507 case 'twentyfifteen':
508 $selector = '#main';
509 break;
510 case 'twentyfourteen':
511 $selector = 'article';
512 break;
513 }
514
515 // Don't relocate if the ad is being placed manually.
516 if ( doing_action( 'wordads_header_ad' ) ) {
517 $selector = '';
518 }
519
520 $section_id = 0 === $this->params->blog_id ? WORDADS_API_TEST_ID : $this->params->blog_id . '2';
521 $form_factor = $this->params->mobile_device ? 'square' : 'leaderboard';
522 echo $this->get_dynamic_ad_snippet( $section_id, $form_factor, 'top', $selector ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
523 }
524
525 /**
526 * Header unit for AMP
527 *
528 * @param string $content Content of the page.
529 *
530 * @since 7.5.0
531 */
532 public function insert_header_ad_amp( $content ) {
533
534 $ad_type = $this->option( 'wordads_house' ) ? 'house' : 'iponweb';
535 if ( 'house' === $ad_type ) {
536 return $content;
537 }
538 return $this->get_ad( 'top_amp', $ad_type ) . $content;
539 }
540
541 /**
542 * Filter the latest ads.txt to include custom user entries. Strips any tags or whitespace.
543 *
544 * @param string $adstxt The ads.txt being filtered.
545 * @return string Filtered ads.txt with custom entries, if applicable.
546 *
547 * @since 6.5.0
548 */
549 public function insert_custom_adstxt( $adstxt ) {
550 if ( ! $this->option( 'wordads_custom_adstxt_enabled' ) ) {
551 return $adstxt;
552 }
553
554 $custom_adstxt = trim( wp_strip_all_tags( $this->option( 'wordads_custom_adstxt' ) ) );
555 if ( $custom_adstxt ) {
556 $adstxt .= "\n\n#Jetpack - User Custom Entries\n";
557 $adstxt .= $custom_adstxt . "\n";
558 }
559
560 return $adstxt;
561 }
562
563 /**
564 * Get the ad for the spot and type.
565 *
566 * @param string $spot top, side, inline, or belowpost.
567 * @param string $type iponweb or adsense.
568 */
569 public function get_ad( $spot, $type = 'iponweb' ) {
570 $snippet = '';
571 if ( 'iponweb' === $type ) {
572 $section_id = WORDADS_API_TEST_ID;
573 $snippet = '';
574
575 if ( 'top' === $spot ) {
576 // mrec for mobile, leaderboard for desktop.
577 $section_id = 0 === $this->params->blog_id ? WORDADS_API_TEST_ID : $this->params->blog_id . '2';
578 $form_factor = $this->params->mobile_device ? 'square' : 'leaderboard';
579 $snippet = $this->get_dynamic_ad_snippet( $section_id, $form_factor, $spot );
580 } elseif ( 'belowpost' === $spot ) {
581 $section_id = 0 === $this->params->blog_id ? WORDADS_API_TEST_ID : $this->params->blog_id . '1';
582 $snippet = $this->get_dynamic_ad_snippet( $section_id, 'square', $spot );
583 } elseif ( 'inline' === $spot ) {
584 $section_id = 0 === $this->params->blog_id ? WORDADS_API_TEST_ID : $this->params->blog_id . '5';
585 $snippet = $this->get_dynamic_ad_snippet( $section_id, 'square', $spot );
586 } elseif ( 'top_amp' === $spot ) {
587 // Ad unit which can safely be inserted below title, above content in a variety of themes.
588 $width = 300;
589 $height = 250;
590 $snippet = $this->get_ad_div( $spot, $this->get_amp_snippet( $height, $width ) );
591 }
592 } elseif ( 'house' === $type ) {
593 $leaderboard = 'top' === $spot && ! $this->params->mobile_device;
594 $snippet = $this->get_house_ad( $leaderboard ? 'leaderboard' : 'mrec' );
595 if ( 'belowpost' === $spot && $this->option( 'wordads_second_belowpost', true ) ) {
596 $snippet .= $this->get_house_ad( $leaderboard ? 'leaderboard' : 'mrec' );
597 }
598 }
599
600 return $snippet;
601 }
602
603 /**
604 * Returns the AMP snippet to be inserted
605 *
606 * @param int $height Height.
607 * @param int $width Width.
608 * @return string
609 *
610 * @since 8.7
611 */
612 public function get_amp_snippet( $height, $width ) {
613 $height = esc_attr( $height + 15 ); // this will ensure enough padding for "Report this ad".
614 $width = esc_attr( $width );
615 $amp_section_id = esc_attr( self::get_amp_section_id() );
616 $site_id = esc_attr( $this->params->blog_id );
617 return <<<HTML
618 <amp-ad width="$width" height="$height"
619 type="pubmine"
620 data-siteid="$site_id"
621 data-section="$amp_section_id">
622 </amp-ad>
623 HTML;
624 }
625
626 /**
627 * Compatibility function -- main functionality replaced with get_dynamic_ad_snippet
628 *
629 * @param int $section_id Ad section.
630 * @param int $height Ad height.
631 * @param int $width Ad width.
632 * @param string $location Location.
633 * @param string $css CSS.
634 *
635 * @return string
636 *
637 * @since 5.7
638 */
639 public function get_ad_snippet( $section_id, $height, $width, $location = '', $css = '' ) {
640 if ( class_exists( 'Jetpack_AMP_Support' ) && Jetpack_AMP_Support::is_amp_request() ) {
641 return $this->get_amp_snippet( $height, $width );
642 }
643
644 $this->ads[] = array(
645 'location' => $location,
646 'width' => $width,
647 'height' => $height,
648 );
649
650 if ( 'gutenberg' === $location ) {
651 $ad_number = count( $this->ads ) . '-' . uniqid();
652 $data_tags = $this->params->cloudflare ? ' data-cfasync="false"' : '';
653 $css = esc_attr( $css );
654
655 $loc_id = 100;
656 if ( ! empty( self::$ad_location_ids[ $location ] ) ) {
657 $loc_id = self::$ad_location_ids[ $location ];
658 }
659
660 $loc_id = esc_js( $loc_id );
661 return <<<HTML
662 <div style="padding-bottom:15px;width:{$width}px;height:{$height}px;$css">
663 <div id="atatags-{$ad_number}">
664 <script$data_tags type="text/javascript">
665 __ATA.cmd.push(function() {
666 __ATA.initSlot('atatags-{$ad_number}', {
667 collapseEmpty: 'before',
668 sectionId: '{$section_id}',
669 location: {$loc_id},
670 width: {$width},
671 height: {$height}
672 });
673 });
674 </script>
675 </div>
676 </div>
677 HTML;
678 }
679
680 $form_factor = 'square';
681 if ( 250 > $width ) {
682 $form_factor = 'skyscraper';
683 } elseif ( 300 < $width ) {
684 $form_factor = 'leaderboard';
685 }
686
687 return $this->get_dynamic_ad_snippet( $section_id, $form_factor, $location );
688 }
689
690 /**
691 * Returns the dynamic snippet to be inserted into the ad unit
692 *
693 * @param int $section_id section_id.
694 * @param string $form_factor form_factor.
695 * @param string $location location.
696 * @param string $relocate location to be moved after the fact for themes without required hook.
697 * @return string
698 *
699 * @since 8.7
700 */
701 public function get_dynamic_ad_snippet( $section_id, $form_factor = 'square', $location = '', $relocate = '' ) {
702 $div_id = 'atatags-' . $section_id . '-' . uniqid();
703 $div_id = esc_attr( $div_id );
704
705 // Default form factor.
706 $form_factor_id = self::$form_factor_ids['square'];
707 if ( isset( self::$form_factor_ids[ $form_factor ] ) ) {
708 $form_factor_id = self::$form_factor_ids[ $form_factor ];
709 }
710
711 $loc_id = 100;
712 if ( isset( self::$ad_location_ids[ $location ] ) ) {
713 $loc_id = self::$ad_location_ids[ $location ];
714 }
715
716 $form_factor_id = esc_js( $form_factor_id );
717 $advertisements_text = esc_js( __( 'Advertisements', 'jetpack' ) );
718 $report_ad_text = esc_js( __( 'Report this ad', 'jetpack' ) );
719 $privacy_settings_text = esc_js( __( 'Privacy settings', 'jetpack' ) );
720
721 $relocate_script = '';
722 if ( ! empty( $relocate ) ) {
723 $selector = wp_json_encode( $relocate );
724 $relocate_script = <<<JS
725 <script type="text/javascript">
726 var adNode = document.getElementById( '{$div_id}' );
727 var selector = {$selector};
728 var relocateNode = document.querySelector( selector );
729 relocateNode.parentNode.insertBefore( adNode, relocateNode );
730 </script>
731 JS;
732 }
733
734 return <<<HTML
735 <div id="{$div_id}"></div>
736 {$relocate_script}
737 <script>
738 __ATA.cmd.push(function() {
739 __ATA.initDynamicSlot({
740 id: '{$div_id}',
741 location: {$loc_id},
742 formFactor: '{$form_factor_id}',
743 label: {
744 text: '{$advertisements_text}',
745 },
746 creative: {
747 reportAd: {
748 text: '{$report_ad_text}',
749 },
750 privacySettings: {
751 text: '{$privacy_settings_text}',
752 onClick: function() { window.__tcfapi && window.__tcfapi('showUi'); },
753 }
754 }
755 });
756 });
757 </script>
758 HTML;
759 }
760
761 /**
762 * Returns the complete ad div with snippet to be inserted into the page
763 *
764 * @param string $spot top, side, inline, or belowpost.
765 * @param string $snippet The snippet to insert into the div.
766 * @param array $css_classes CSS classes.
767 * @return string The supporting ad unit div.
768 *
769 * @since 7.1
770 */
771 public function get_ad_div( $spot, $snippet, array $css_classes = array() ) {
772 if ( strpos( strtolower( $spot ), 'amp' ) === false && ! 'inline' === $spot ) {
773 return $snippet; // we don't want dynamic ads to be inserted for AMP & Gutenberg.
774 }
775
776 if ( empty( $css_classes ) ) {
777 $css_classes = array();
778 }
779
780 $css_classes[] = 'wpcnt';
781 if ( 'top' === $spot ) {
782 $css_classes[] = 'wpcnt-header';
783 }
784
785 $spot = esc_attr( $spot );
786 $classes = esc_attr( implode( ' ', $css_classes ) );
787 $about = esc_html__( 'Advertisements', 'jetpack' );
788 return <<<HTML
789 <div class="$classes">
790 <div class="wpa">
791 <span class="wpa-about">$about</span>
792 <div class="u $spot">
793 $snippet
794 </div>
795 </div>
796 </div>
797 HTML;
798 }
799
800 /**
801 * Check the reasons to bail before we attempt to insert ads.
802 *
803 * @return true if we should bail (don't insert ads)
804 *
805 * @since 4.5.0
806 */
807 public function should_bail() {
808 return ! $this->option( 'wordads_approved' ) || (bool) $this->option( 'wordads_unsafe' );
809 }
810
811 /**
812 * Returns markup for HTML5 house ad base on unit
813 *
814 * @param string $unit mrec, widesky, or leaderboard.
815 * @return string markup for HTML5 house ad
816 *
817 * @since 4.7.0
818 */
819 public function get_house_ad( $unit = 'mrec' ) {
820
821 switch ( $unit ) {
822 case 'widesky':
823 $width = 160;
824 $height = 600;
825 break;
826 case 'leaderboard':
827 $width = 728;
828 $height = 90;
829 break;
830 case 'mrec':
831 default:
832 $width = 300;
833 $height = 250;
834 break;
835 }
836
837 return <<<HTML
838 <iframe
839 src="https://s0.wp.com/wp-content/blog-plugins/wordads/house/html5/$unit/index.html"
840 width="$width"
841 height="$height"
842 frameborder="0"
843 scrolling="no"
844 marginheight="0"
845 marginwidth="0">
846 </iframe>
847 HTML;
848 }
849
850 /**
851 * Activation hook actions
852 *
853 * @since 4.5.0
854 */
855 public static function activate() {
856 WordAds_API::update_wordads_status_from_api();
857 }
858
859 /**
860 * Registers the widgets.
861 */
862 public function widget_callback() {
863 register_widget( 'WordAds_Sidebar_Widget' );
864
865 $ccpa_enabled = get_option( 'wordads_ccpa_enabled' );
866
867 if ( $ccpa_enabled ) {
868 register_widget( 'WordAds_Ccpa_Do_Not_Sell_Link_Widget' );
869 }
870 }
871 }
872
873 add_action( 'jetpack_activate_module_wordads', array( 'WordAds', 'activate' ) );
874 add_action( 'jetpack_activate_module_wordads', array( 'WordAds_Cron', 'activate' ) );
875 add_action( 'jetpack_deactivate_module_wordads', array( 'WordAds_Cron', 'deactivate' ) );
876
877 global $wordads;
878 $wordads = new WordAds();
879