db = RT_WA_Analytics_DB::instance(); $this->settings = RT_WA_Analytics_Settings::instance(); add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_tracker' ) ); add_action( 'wp_body_open', array( $this, 'output_gtm_noscript' ), 1 ); // Fallback for themes that never call wp_body_open(). The method is a // no-op once the body-open hook has printed the noscript block. add_action( 'wp_footer', array( $this, 'output_gtm_noscript' ), 20 ); } /** * Read the visitor's stored consent choice. * * @return string "accepted", "declined" or an empty string when not set. */ private function get_consent() { if ( ! isset( $_COOKIE['rt_wa_consent'] ) ) { return ''; } return sanitize_text_field( wp_unslash( $_COOKIE['rt_wa_consent'] ) ); } public function is_tracking_enabled() { if ( $this->settings->get( 'enable_tracking' ) !== 'yes' ) { return false; } if ( $this->settings->get( 'privacy_consent_enable' ) === 'yes' ) { $consent = $this->get_consent(); if ( $consent === 'declined' ) { return false; } // Strict GDPR mode: do not process any visitor data before an // explicit "Accept" choice has been recorded. if ( $this->settings->get( 'privacy_gdpr_mode' ) === 'yes' && $consent !== 'accepted' ) { return false; } } if ( $this->settings->get( 'ignore_admin' ) === 'yes' && current_user_can( 'manage_options' ) ) { return false; } if ( $this->settings->get( 'ignore_logged_in' ) === 'yes' && is_user_logged_in() ) { return false; } $excluded_roles = $this->settings->get( 'excluded_roles', array() ); if ( ! empty( $excluded_roles ) && is_user_logged_in() ) { $user = wp_get_current_user(); foreach ( (array) $excluded_roles as $role ) { if ( in_array( $role, (array) $user->roles, true ) ) { return false; } } } $excluded_pages = $this->settings->get( 'excluded_pages', '' ); if ( ! empty( $excluded_pages ) ) { $pages = explode( "\n", $excluded_pages ); $current_url = $this->get_current_url(); foreach ( $pages as $page ) { $page = trim( $page ); if ( ! empty( $page ) && strpos( $current_url, $page ) !== false ) { return false; } } } return true; } /** * Whether third-party tags may be loaded or receive forwarded events for * this request. When the consent banner is enabled, tagging is only * allowed after the visitor has explicitly accepted. * * @return bool */ private function is_third_party_allowed() { if ( $this->settings->get( 'privacy_consent_enable' ) !== 'yes' ) { return true; } return $this->get_consent() === 'accepted'; } /** * Validated Google Tag Manager container ID. * * @return string Empty string when disabled or invalid. */ private function get_gtm_id() { if ( $this->settings->get( 'integration_gtm_enable' ) !== 'yes' ) { return ''; } $gtm_id = strtoupper( trim( (string) $this->settings->get( 'integration_gtm_id', '' ) ) ); if ( ! preg_match( '/^GTM-[A-Z0-9]+$/', $gtm_id ) ) { return ''; } return $gtm_id; } public function enqueue_tracker() { if ( ! $this->is_tracking_enabled() ) { return; } $gtm_id = $this->get_gtm_id(); $third_party_allowed = $this->is_third_party_allowed(); $gtm_allowed = '' !== $gtm_id && $third_party_allowed; wp_enqueue_script( 'rt-wa-analytics-tracker', RT_WA_ANALYTICS_URL . 'modules/tracking/js/tracker.js', array(), RT_WA_ANALYTICS_VERSION, array( 'strategy' => 'defer', 'in_footer' => true, ) ); $tracker_data = array( 'ajaxUrl' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'rt_wa_tracker_nonce' ), 'cookieLifetime' => (int) $this->settings->get( 'cookie_lifetime', 30 ), 'sessionTimeout' => (int) $this->settings->get( 'session_timeout', 30 ) * 60, 'visitorUuid' => $this->get_visitor_uuid(), 'sessionId' => $this->get_session_id(), 'currentUrl' => $this->get_current_url(), 'referrer' => isset( $_SERVER['HTTP_REFERER'] ) ? esc_url_raw( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) : '', 'debug' => $this->settings->get( 'debug_mode' ) === 'yes', 'maskIp' => $this->settings->get( 'privacy_mask_ip' ) === 'yes', 'ga4Id' => $this->settings->get( 'integration_ga4_enable' ) === 'yes' ? $this->settings->get( 'integration_ga4_id' ) : '', 'gtmId' => $gtm_allowed ? $gtm_id : '', 'metaPixelId' => $this->settings->get( 'integration_meta_enable' ) === 'yes' ? $this->settings->get( 'integration_meta_pixel_id' ) : '', 'metaEventName' => $this->settings->get( 'integration_meta_event_name' ), 'tiktokPixelId' => $this->settings->get( 'integration_tiktok_pixel_id' ), 'snapchatPixelId' => $this->settings->get( 'integration_snapchat_pixel_id' ), 'pinterestTagId' => $this->settings->get( 'integration_pinterest_tag_id' ), 'twitterPixelId' => $this->settings->get( 'integration_twitter_pixel_id' ), 'linkedinInsightId' => $this->settings->get( 'integration_linkedin_insight_id' ), 'googleAdsId' => $this->settings->get( 'integration_google_ads_id' ), 'clarityProjectId' => $this->settings->get( 'integration_clarity_project_id' ), 'bingUetId' => $this->settings->get( 'integration_bing_uet_id' ), 'redditPixelId' => $this->settings->get( 'integration_reddit_pixel_id' ), 'quoraPixelId' => $this->settings->get( 'integration_quora_pixel_id' ), 'yandexMetrikaId' => $this->settings->get( 'integration_yandex_metrika_id' ), 'hubspotId' => $this->settings->get( 'integration_hubspot_id' ), 'hotjarId' => $this->settings->get( 'integration_hotjar_id' ), 'whatsappPatterns' => $this->get_whatsapp_patterns(), ); if ( ! $third_party_allowed ) { $third_party_keys = array( 'ga4Id', 'gtmId', 'metaPixelId', 'tiktokPixelId', 'snapchatPixelId', 'pinterestTagId', 'twitterPixelId', 'linkedinInsightId', 'googleAdsId', 'clarityProjectId', 'bingUetId', 'redditPixelId', 'quoraPixelId', 'yandexMetrikaId', 'hubspotId', 'hotjarId', ); foreach ( $third_party_keys as $key ) { $tracker_data[ $key ] = ''; } } wp_localize_script( 'rt-wa-analytics-tracker', 'rtWaTracker', $tracker_data ); if ( $gtm_allowed ) { // Inline-only handle: no external file, the loader is attached with // the WordPress script API and printed with the footer scripts. wp_register_script( 'zaaecl_gtm', false, array(), ZAAECL_VERSION, true ); wp_enqueue_script( 'zaaecl_gtm' ); wp_add_inline_script( 'zaaecl_gtm', $this->get_gtm_loader_js( $gtm_id ) ); } } /** * Build the GTM loader snippet. * * @param string $gtm_id Validated GTM container ID. * @return string */ private function get_gtm_loader_js( $gtm_id ) { return "(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!=='dataLayer'?'&l='+l:'';j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+encodeURIComponent(i)+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','" . esc_js( $gtm_id ) . "');"; } /** * Print the GTM