PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 5.1.3
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v5.1.3
5.13.0 5.12.1 5.12.0 5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / classes / WpMatomo / Admin / TrackingSettings.php
matomo / classes / WpMatomo / Admin Last commit date
TrackingSettings 1 year ago views 1 year ago AccessSettings.php 4 years ago Admin.php 1 year ago AdminSettings.php 2 years ago AdminSettingsInterface.php 6 years ago AdvancedSettings.php 2 years ago Chart.php 4 years ago CookieConsent.php 4 years ago Dashboard.php 4 years ago ExclusionSettings.php 4 years ago GeolocationSettings.php 2 years ago GetStarted.php 4 years ago ImportWpStatistics.php 4 years ago Info.php 4 years ago InvalidIpException.php 4 years ago Marketplace.php 2 years ago MarketplaceSetupWizard.php 1 year ago Menu.php 1 year ago PluginMeasurableSettings.php 2 years ago PrivacySettings.php 4 years ago SafeModeMenu.php 4 years ago Summary.php 4 years ago SystemReport.php 2 years ago TrackingSettings.php 1 year ago
TrackingSettings.php
455 lines
1 <?php
2 /**
3 * Matomo - free/libre analytics platform
4 *
5 * @link https://matomo.org
6 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
7 * @package matomo
8 */
9
10 namespace WpMatomo\Admin;
11
12 use Exception;
13 use WpMatomo\Capabilities;
14 use WpMatomo\Settings;
15 use WpMatomo\Site;
16 use WpMatomo\Site\Sync\SyncConfig as SiteConfigSync;
17 use WpMatomo\TrackingCode\GeneratorOptions;
18 use WpMatomo\TrackingCode\TrackingCodeGenerator;
19
20 if ( ! defined( 'ABSPATH' ) ) {
21 exit; // if accessed directly
22 }
23 /**
24 * TODO: maybe we can move the form data collection to a single class
25 * Note: nonce verification exists, but phpcs can't tell since it's in a method
26 * that calls other methods that then access post data.
27 * phpcs:disable WordPress.Security.NonceVerification.Missing
28 */
29 class TrackingSettings implements AdminSettingsInterface {
30 const FORM_NAME = 'matomo';
31 const NONCE_NAME = 'matomo_settings';
32 const TRACK_MODE_DEFAULT = 'default';
33 const TRACK_MODE_DISABLED = 'disabled';
34 const TRACK_MODE_MANUALLY = 'manually';
35 const TRACK_MODE_TAGMANAGER = 'tagmanager';
36 const NONCE_NAME_GENERATE_TRACKING_CODE_AJAX = 'matomo-tracking-settings-code';
37
38 /**
39 * @var Settings
40 */
41 private $settings;
42
43 /**
44 * @param Settings $settings
45 */
46 public function __construct( $settings ) {
47 $this->settings = $settings;
48 $this->add_hooks();
49 }
50
51 public function get_title() {
52 return esc_html__( 'Tracking', 'matomo' );
53 }
54
55 private function update_if_submitted() {
56 if ( $this->form_submitted() === true
57 && check_admin_referer( self::NONCE_NAME ) ) {
58 $this->apply_settings();
59
60 return true;
61 }
62
63 return false;
64 }
65
66 public function can_user_manage() {
67 return current_user_can( Capabilities::KEY_SUPERUSER );
68 }
69
70 private function apply_settings() {
71 $keys_to_keep = [
72 'track_mode',
73 'track_across',
74 'track_across_alias',
75 'track_crossdomain_linking',
76 'track_feed',
77 'track_feed_addcampaign',
78 'track_feed_campaign',
79 'track_heartbeat',
80 'track_user_id',
81 'track_datacfasync',
82 'tagmanger_container_ids',
83 'set_download_extensions',
84 'set_download_classes',
85 'set_link_classes',
86 'track_admin',
87 'limit_cookies_referral',
88 'limit_cookies_session',
89 'limit_cookies_visitor',
90 'limit_cookies',
91 'force_post',
92 'disable_cookies',
93 'cookie_consent',
94 'add_download_extensions',
95 'track_404',
96 'track_search',
97 'add_post_annotations',
98 'track_content',
99 'track_ecommerce',
100 'track_noscript',
101 'noscript_code',
102 'track_codeposition',
103 'tracking_code',
104 'force_protocol',
105 'track_js_endpoint',
106 'track_jserrors',
107 'track_api_endpoint',
108 Settings::SITE_CURRENCY,
109 ];
110
111 if ( matomo_has_tag_manager() ) {
112 $keys_to_keep[] = 'tagmanger_container_ids';
113 }
114
115 $values = [];
116
117 // default value in case no role/ post type is selected to make sure we unset it if no role /post type is selected
118 $values['add_post_annotations'] = [];
119 $values['tagmanger_container_ids'] = [];
120
121 $valid_currencies = $this->get_supported_currencies();
122
123 if ( ! empty( $_POST[ self::FORM_NAME ]['tracker_debug'] ) ) {
124 $site_config_sync = new SiteConfigSync( $this->settings );
125 switch ( $_POST[ self::FORM_NAME ]['tracker_debug'] ) {
126 case 'always':
127 $site_config_sync->set_config_value( 'Tracker', 'debug', 1 );
128 $site_config_sync->set_config_value( 'Tracker', 'debug_on_demand', 0 );
129 break;
130 case 'on_demand':
131 $site_config_sync->set_config_value( 'Tracker', 'debug', 0 );
132 $site_config_sync->set_config_value( 'Tracker', 'debug_on_demand', 1 );
133 break;
134 default:
135 $site_config_sync->set_config_value( 'Tracker', 'debug', 0 );
136 $site_config_sync->set_config_value( 'Tracker', 'debug_on_demand', 0 );
137 }
138 }
139
140 if ( empty( $_POST[ self::FORM_NAME ][ Settings::SITE_CURRENCY ] )
141 || ! array_key_exists( sanitize_text_field( wp_unslash( $_POST[ self::FORM_NAME ][ Settings::SITE_CURRENCY ] ) ), $valid_currencies ) ) {
142 $_POST[ self::FORM_NAME ][ Settings::SITE_CURRENCY ] = 'USD';
143 }
144
145 if ( ! empty( $_POST[ self::FORM_NAME ]['track_mode'] ) ) {
146 $track_mode = $this->get_track_mode();
147 if ( self::TRACK_MODE_TAGMANAGER === $track_mode ) {
148 // no noscript mode in this case
149 $_POST[ self::FORM_NAME ]['track_noscript'] = '';
150 $_POST[ self::FORM_NAME ]['noscript_code'] = '';
151 } else {
152 unset( $_POST['tagmanger_container_ids'] );
153 }
154 if ( $this->must_update_tracker() === true ) {
155 // We want to keep the tracking code when user switches between disabled and manually or disabled to disabled.
156 if ( ! empty( $_POST[ self::FORM_NAME ]['tracking_code'] ) ) {
157 // don't process, this is a script
158 // phpcs:disable WordPress.Security.ValidatedSanitizedInput
159 $_POST[ self::FORM_NAME ]['tracking_code'] = stripslashes( $_POST[ self::FORM_NAME ]['tracking_code'] );
160 // phpcs:enable WordPress.Security.ValidatedSanitizedInput
161 } else {
162 $_POST[ self::FORM_NAME ]['tracking_code'] = '';
163 }
164 if ( ! empty( $_POST[ self::FORM_NAME ]['noscript_code'] ) ) {
165 // don't process, this is a script
166 // phpcs:disable WordPress.Security.ValidatedSanitizedInput
167 $_POST[ self::FORM_NAME ]['noscript_code'] = stripslashes( $_POST[ self::FORM_NAME ]['noscript_code'] );
168 // phpcs:enable WordPress.Security.ValidatedSanitizedInput
169 } else {
170 $_POST[ self::FORM_NAME ]['noscript_code'] = '';
171 }
172 } else {
173 $_POST[ self::FORM_NAME ]['noscript_code'] = '';
174 $_POST[ self::FORM_NAME ]['tracking_code'] = '';
175 }
176 }
177 // phpcs:disable WordPress.Security.ValidatedSanitizedInput
178 foreach ( $_POST[ self::FORM_NAME ] as $name => $value ) {
179 if ( in_array( $name, $keys_to_keep, true ) ) {
180 $values[ $name ] = $value;
181 }
182 }
183 // phpcs:enable WordPress.Security.ValidatedSanitizedInput
184 $this->settings->apply_tracking_related_changes( $values );
185
186 return true;
187 }
188
189 private function get_track_mode() {
190 if ( ! empty( $_POST[ self::FORM_NAME ]['track_mode'] ) ) {
191 return sanitize_text_field( wp_unslash( $_POST[ self::FORM_NAME ]['track_mode'] ) );
192 }
193 return '';
194 }
195 /**
196 * Reauires form to be posted
197 *
198 * @return bool
199 */
200 private function must_update_tracker() {
201 $track_mode = $this->get_track_mode();
202 $previus_track_mode = $this->settings->get_global_option( 'track_mode' );
203 $must_update = false;
204 if ( self::TRACK_MODE_MANUALLY === $track_mode
205 || ( self::TRACK_MODE_DISABLED === $track_mode &&
206 in_array( $previus_track_mode, [ self::TRACK_MODE_DISABLED, self::TRACK_MODE_MANUALLY ], true ) ) ) {
207 // We want to keep the tracking code when user switches between disabled and manually or disabled to disabled.
208 $must_update = true;
209 }
210
211 return $must_update;
212 }
213
214 /**
215 * @return bool
216 */
217 private function form_submitted() {
218 return isset( $_POST ) && ! empty( $_POST[ self::FORM_NAME ] )
219 && is_admin()
220 && $this->can_user_manage();
221 }
222
223 /**
224 * @param string $field
225 *
226 * @return bool
227 */
228 private function has_valid_html_comments( $field ) {
229 $valid = true;
230 if ( $this->form_submitted() === true ) {
231 if ( $this->must_update_tracker() === true ) {
232 if ( ! empty( $_POST[ self::FORM_NAME ][ $field ] ) ) {
233 // phpcs:disable WordPress.Security.ValidatedSanitizedInput
234 $valid = $this->validate_html_comments( $_POST[ self::FORM_NAME ][ $field ] );
235 // phpcs:enable WordPress.Security.ValidatedSanitizedInput
236 }
237 }
238 }
239
240 return $valid;
241 }
242
243 /**
244 * @param string $html html content to validate
245 *
246 * @returns boolean
247 */
248 public function validate_html_comments( $html ) {
249 $opening = substr_count( $html, '<!--' );
250 $closing = substr_count( $html, '-->' );
251
252 return ( $opening === $closing );
253 }
254
255 public function show_settings() {
256 $was_updated = false;
257 $settings_errors = [];
258 if ( $this->has_valid_html_comments( 'tracking_code' ) !== true ) {
259 $settings_errors[] = __( 'Settings have not been saved. There is an issue with the HTML comments in the field "Tracking code". Make sure all opened comments (<!--) are closed (-->) correctly.', 'matomo' );
260 }
261 if ( $this->has_valid_html_comments( 'noscript_code' ) !== true ) {
262 $settings_errors[] = __( 'Settings have not been saved. There is an issue with the HTML comments in the field "Noscript code". Make sure all opened comments (<!--) are closed (-->) correctly.', 'matomo' );
263 }
264 if ( count( $settings_errors ) === 0 ) {
265 $was_updated = $this->update_if_submitted();
266 }
267
268 $settings = $this->settings;
269
270 $containers = $this->get_active_containers();
271
272 $track_modes = [
273 self::TRACK_MODE_DEFAULT => [
274 'name' => esc_html__( 'Auto (recommended)', 'matomo' ),
275 'disabled' => false,
276 ],
277 self::TRACK_MODE_MANUALLY => [
278 'name' => esc_html__( 'Manual', 'matomo' ),
279 'disabled' => false,
280 ],
281 self::TRACK_MODE_TAGMANAGER => [
282 'name' => esc_html__( 'Tag Manager', 'matomo' ),
283 'disabled' => false,
284 ],
285 self::TRACK_MODE_DISABLED => [
286 'name' => esc_html__( 'Disabled', 'matomo' ),
287 'disabled' => false,
288 ],
289 ];
290
291 $matomo_track_mode_descriptions = [
292 self::TRACK_MODE_DISABLED => esc_html__( 'Matomo will not add the tracking code itself. Use this mode if you want to add the tracking code by hand to your template files or you want to use another plugin to add the tracking code.', 'matomo' ),
293 self::TRACK_MODE_DEFAULT => esc_html__( 'Matomo will automatically generate and embed the tracking code based on the Auto Tracking settings below.', 'matomo' ) . ' ' . esc_html__( 'This is the recommended mode for most users.', 'matomo' ),
294 self::TRACK_MODE_MANUALLY => sprintf(
295 esc_html__( '%1$sDefine your own tracking JavaScript by hand below%2$s, and Matomo will embed it into your website.', 'matomo' ) . ( $settings->is_network_enabled() ? ' ' . esc_html__( 'Make sure to use the placeholder {ID} to add the Matomo site ID.', 'matomo' ) : '' ),
296 '<a href="#manual-tracking-settings">',
297 '</a>'
298 ),
299 self::TRACK_MODE_TAGMANAGER => esc_html__( 'If you\'ve created containers in the Tag Manager, you can use this tracking mode to embed one or more of them into your website automatically.', 'matomo' ),
300 ];
301
302 if ( empty( $containers ) ) {
303 $track_modes[ self::TRACK_MODE_TAGMANAGER ]['disabled'] = true;
304 $track_modes[ self::TRACK_MODE_TAGMANAGER ]['tooltip'] = esc_html__( 'No containers were found. Create one to be able to use the Tag Manager tracking mode.', 'matomo' );
305 $matomo_track_mode_descriptions[ self::TRACK_MODE_TAGMANAGER ] .= ' ' . esc_html__( 'This mode is not selectable since no containers have been created in the Tag Manager.', 'matomo' );
306 } else {
307 $container_select = '<div style="margin-left:1.5em" class="tagmanager-container-select">'
308 . '<label for="tagmanger_container_ids">' . esc_html__( 'Select which Tag Manager containers will be added to each page', 'matomo' ) . ':</label>';
309
310 $selected_container_ids = $settings->get_global_option( 'tagmanger_container_ids' );
311 foreach ( $containers as $container_id => $container_name ) {
312 $container_select .= '<input type="checkbox" ' . ( isset( $selected_container_ids [ $container_id ] ) && $selected_container_ids [ $container_id ] ? 'checked="checked" ' : '' ) . 'value="1" name="matomo[tagmanger_container_ids][' . esc_attr( $container_id ) . ']" /> <strong>' . esc_html( $container_name ) . '</strong> (ID: ' . esc_html( $container_id ) . ')&nbsp; <br />';
313 }
314
315 $container_select .= '<a style="margin-top:.5em;display:inline-block;" href="' . esc_url( menu_page_url( \WpMatomo\Admin\Menu::SLUG_TAGMANAGER, false ) ) . '" rel="noreferrer noopener" target="_blank">Edit containers <span class="dashicons-before dashicons-external"></span></a>';
316 $container_select .= '<p style="margin-top:1em"><span class="dashicons dashicons-info-outline"></span> ' . sprintf( esc_html__( 'For Matomo to track you will need to %1$sadd a Matomo Tag to the container%2$s. It otherwise won\'t track automatically.', 'matomo' ), '<a href="https://matomo.org/faq/tag-manager/how-do-i-track-pageviews-of-my-website-using-matomo-tag-manager/" target="_blank" rel="noreferrer noopener">', '</a>' ) . '</p>';
317 $container_select .= '</div>';
318
319 $matomo_track_mode_descriptions[ self::TRACK_MODE_TAGMANAGER ] .= $container_select;
320 }
321
322 $matomo_track_mode_descriptions[ self::TRACK_MODE_TAGMANAGER ] .= '<a id="tagmanager-read-more-link" style="display:inline-block" href="https://matomo.org/guide/tag-manager/getting-started-with-tag-manager/" target="_blank" rel="noreferrer noopener">' . esc_html__( 'Read our documentation on the Matomo Tag Manager to learn more.', 'matomo' ) . '</a>';
323
324 // /var/www/html/test/wp-content/uploads/wp-statistics/GeoLite2-City.mmdb
325 $site = new Site();
326 $idsite = $site->get_current_matomo_site_id();
327
328 $matomo_currencies = $this->get_supported_currencies();
329
330 $cookie_consent_modes = $this->get_cookie_consent_modes();
331
332 $tracking_code_generator = new TrackingCodeGenerator( $this->settings, new GeneratorOptions( $this->settings ) );
333 $matomo_default_tracking_code = $tracking_code_generator->prepare_tracking_code( $idsite );
334
335 $matomo_exclusion_settings_url = home_url( '/wp-admin/admin.php?page=matomo-settings&tab=exlusions' );
336
337 include dirname( __FILE__ ) . '/views/tracking.php';
338 }
339
340 /**
341 * @return string[]
342 */
343 private function get_cookie_consent_modes() {
344 $modes = [];
345 foreach ( CookieConsent::get_available_options() as $option => $description ) {
346 $modes[ $option ] = $description;
347 }
348
349 return $modes;
350 }
351
352 private function get_supported_currencies() {
353 $all = include dirname( MATOMO_ANALYTICS_FILE ) . '/app/core/Intl/Data/Resources/currencies.php';
354 $currencies = [];
355 foreach ( $all as $key => $single ) {
356 $currencies[ $key ] = $single[0] . ' ' . $single[1];
357 }
358
359 return $currencies;
360 }
361
362 public function get_active_containers() {
363 // we don't use Matomo API here to avoid needing to bootstrap Matomo which is slow and could break things
364 $containers = [];
365 if ( matomo_has_tag_manager() ) {
366 global $wpdb;
367 $db_settings = new \WpMatomo\Db\Settings();
368 $container_table = $db_settings->prefix_table_name( 'tagmanager_container' );
369 try {
370 // phpcs:disable WordPress.DB
371 $containers = $wpdb->get_results( sprintf( 'SELECT `idcontainer`, `name` FROM %s where `status` = "active"', $container_table ) );
372 // phpcs:enable WordPress.DB
373 } catch ( Exception $e ) {
374 // table may not exist yet etc
375 $containers = [];
376 }
377 }
378 $by_id = [];
379 foreach ( $containers as $container ) {
380 $by_id[ $container->idcontainer ] = $container->name;
381 }
382
383 return $by_id;
384 }
385
386 private function add_hooks() {
387 add_action(
388 'admin_enqueue_scripts',
389 function ( $page ) {
390 if ( 'matomo-analytics_page_matomo-settings' !== $page ) {
391 return;
392 }
393
394 wp_enqueue_script(
395 'matomo-tracking-settings',
396 plugins_url( '/assets/js/settings.js', MATOMO_ANALYTICS_FILE ),
397 [ 'jquery' ],
398 '1.0.1',
399 true
400 );
401
402 wp_localize_script(
403 'matomo-tracking-settings',
404 'mtmTrackingSettingsAjax',
405 [
406 'ajax_url' => admin_url( 'admin-ajax.php' ),
407 'nonce' => wp_create_nonce( self::NONCE_NAME_GENERATE_TRACKING_CODE_AJAX ),
408 ]
409 );
410 }
411 );
412 }
413
414 public static function register_ajax() {
415 add_action( 'wp_ajax_matomo_generate_tracking_code', [ self::class, 'generate_tracking_code' ] );
416 }
417
418 public static function generate_tracking_code() {
419 check_ajax_referer( self::NONCE_NAME_GENERATE_TRACKING_CODE_AJAX );
420
421 $blog_id = get_current_blog_id();
422 $idsite = Site::get_matomo_site_id( $blog_id );
423
424 // phpcs complains if reading from $_POST is not done this way
425 $overrides = [
426 'track_datacfasync' => isset( $_POST['track_datacfasync'] ) ? ( boolval( wp_unslash( $_POST['track_datacfasync'] ) ) ) : false,
427 'track_content' => isset( $_POST['track_content'] ) ? ( sanitize_text_field( wp_unslash( $_POST['track_content'] ) ) ) : '',
428 'track_heartbeat' => isset( $_POST['track_heartbeat'] ) ? ( intval( wp_unslash( $_POST['track_heartbeat'] ) ) ) : 0,
429 'limit_cookies' => isset( $_POST['limit_cookies'] ) ? ( boolval( wp_unslash( $_POST['limit_cookies'] ) ) ) : false,
430 'limit_cookies_visitor' => isset( $_POST['limit_cookies_visitor'] ) ? ( intval( wp_unslash( $_POST['limit_cookies_visitor'] ) ) ) : 0,
431 'limit_cookies_session' => isset( $_POST['limit_cookies_session'] ) ? ( intval( wp_unslash( $_POST['limit_cookies_session'] ) ) ) : 0,
432 'limit_cookies_referral' => isset( $_POST['limit_cookies_referral'] ) ? ( intval( wp_unslash( $_POST['limit_cookies_referral'] ) ) ) : 0,
433 'cookie_consent' => isset( $_POST['cookie_consent'] ) ? ( sanitize_text_field( wp_unslash( $_POST['cookie_consent'] ) ) ) : '',
434 'force_post' => isset( $_POST['force_post'] ) ? ( wp_unslash( boolval( $_POST['force_post'] ) ) ) : false,
435 'track_across_alias' => isset( $_POST['track_across_alias'] ) ? ( boolval( wp_unslash( $_POST['track_across_alias'] ) ) ) : false,
436 'track_across' => isset( $_POST['track_across'] ) ? ( boolval( wp_unslash( $_POST['track_across'] ) ) ) : false,
437 'track_crossdomain_linking' => isset( $_POST['track_crossdomain_linking'] ) ? ( boolval( wp_unslash( $_POST['track_crossdomain_linking'] ) ) ) : false,
438 'track_jserrors' => isset( $_POST['track_jserrors'] ) ? ( boolval( wp_unslash( $_POST['track_jserrors'] ) ) ) : false,
439 'disable_cookies' => isset( $_POST['disable_cookies'] ) ? ( boolval( wp_unslash( $_POST['disable_cookies'] ) ) ) : false,
440 'set_link_classes' => isset( $_POST['set_link_classes'] ) ? ( sanitize_text_field( wp_unslash( $_POST['set_link_classes'] ) ) ) : '',
441 'set_download_classes' => isset( $_POST['set_download_classes'] ) ? ( sanitize_text_field( wp_unslash( $_POST['set_download_classes'] ) ) ) : '',
442 'add_download_extensions' => isset( $_POST['add_download_extensions'] ) ? ( sanitize_text_field( wp_unslash( $_POST['add_download_extensions'] ) ) ) : '',
443 'track_api_endpoint' => isset( $_POST['track_api_endpoint'] ) ? ( sanitize_text_field( wp_unslash( $_POST['track_api_endpoint'] ) ) ) : '',
444 'force_protocol' => isset( $_POST['force_protocol'] ) ? ( boolval( wp_unslash( $_POST['force_protocol'] ) ) ) : false,
445 'track_js_endpoint' => isset( $_POST['track_js_endpoint'] ) ? ( sanitize_text_field( wp_unslash( $_POST['track_js_endpoint'] ) ) ) : '',
446 'set_download_extensions' => isset( $_POST['set_download_extensions'] ) ? ( sanitize_text_field( wp_unslash( $_POST['set_download_extensions'] ) ) ) : '',
447 ];
448
449 $generator = new TrackingCodeGenerator( \WpMatomo::$settings, new GeneratorOptions( \WpMatomo::$settings, $overrides ) );
450 $tracking_code = $generator->prepare_tracking_code( $idsite );
451
452 wp_send_json( $tracking_code );
453 }
454 }
455