false, 'strategy' => 'async', ) ); wp_add_inline_script( 'x-pixel-uwt', $base_code, 'before' ); } add_action( 'wp_enqueue_scripts', 'x_pixel_enqueue_tag', 1 ); function x_pixel_sessions() { $sessions = array(); if ( function_exists( 'WC' ) && WC() && WC()->session ) { $sessions[] = WC()->session; } if ( function_exists( 'EDD' ) && EDD() && ! empty( EDD()->session ) ) { $sessions[] = EDD()->session; } return $sessions; } function x_pixel_session() { $sessions = x_pixel_sessions(); return $sessions === array() ? null : $sessions[0]; } function x_pixel_queue_browser_event( $event_id, $params, $session = null ) { $pixel_id = x_pixel_get_id(); $code = x_pixel_event_code( $pixel_id, $event_id ); if ( ! $session ) { $session = x_pixel_session(); } if ( $code === '' || ! $session ) { return false; } $queued = array(); $existing = $session->get( 'x_pixel_queue', array() ); if ( is_array( $existing ) ) { $queued = $existing; } $queued[] = array( 'code' => $code, 'params' => $params, ); $session->set( 'x_pixel_queue', $queued ); return true; } function x_pixel_current_url() { $host = isset( $_SERVER['HTTP_HOST'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ) : ''; $path = isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '/'; if ( $host === '' || preg_match( '/^[A-Za-z0-9.:\[\]-]+$/', $host ) !== 1 ) { return home_url( '/' ); } if ( $path === '' || $path[0] !== '/' ) { $path = '/'; } return esc_url_raw( ( is_ssl() ? 'https://' : 'http://' ) . $host . $path ); } function x_pixel_is_background_request() { return wp_doing_ajax() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) || ( defined( 'WC_DOING_AJAX' ) && WC_DOING_AJAX ); } function x_pixel_is_bot_user_agent() { $user_agent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) : ''; if ( $user_agent === '' ) { return true; } $user_agent = strtolower( $user_agent ); $tokens = array( 'bot', 'crawl', 'spider', 'slurp', 'facebookexternalhit', 'twitterbot', 'googlebot', 'bingbot', 'ahrefsbot', 'semrushbot', 'petalbot', 'python-requests', 'curl', 'wget', 'headlesschrome' ); foreach ( $tokens as $token ) { if ( strpos( $user_agent, $token ) !== false ) { return true; } } return false; } function x_pixel_session_cookie_names() { return array( 'woocommerce_items_in_cart', 'woocommerce_cart_hash', 'edd_items_in_cart' ); } function x_pixel_session_cookie_prefixes() { return array( 'wp_woocommerce_session_', 'edd_session_' ); } function x_pixel_request_cookie_names() { $header = isset( $_SERVER['HTTP_COOKIE'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_COOKIE'] ) ) : ''; $names = array(); foreach ( explode( ';', $header ) as $pair ) { $parts = explode( '=', $pair, 2 ); $name = trim( $parts[0] ); if ( $name !== '' ) { $names[] = $name; } } return $names; } function x_pixel_has_shopper_session() { if ( is_user_logged_in() ) { return true; } $names = x_pixel_session_cookie_names(); $prefixes = x_pixel_session_cookie_prefixes(); foreach ( x_pixel_request_cookie_names() as $cookie ) { if ( in_array( $cookie, $names, true ) ) { return true; } foreach ( $prefixes as $prefix ) { if ( strpos( $cookie, $prefix ) === 0 ) { return true; } } } return false; } function x_pixel_is_untrusted_request( $is_get_add = false ) { if ( x_pixel_has_shopper_session() ) { return false; } if ( x_pixel_is_bot_user_agent() ) { return true; } return $is_get_add && isset( $_SERVER['REQUEST_METHOD'] ) && $_SERVER['REQUEST_METHOD'] === 'GET'; } function x_pixel_event_source_url() { if ( x_pixel_is_background_request() ) { $referer = wp_get_raw_referer(); if ( $referer ) { return esc_url_raw( $referer ); } } return x_pixel_current_url(); } function x_pixel_event_script( $code, $params ) { $code_json = wp_json_encode( (string) $code, x_pixel_json_flags() ); $payload = wp_json_encode( is_array( $params ) ? $params : array(), x_pixel_json_flags() ); if ( ! is_string( $code_json ) ) { return ''; } if ( ! is_string( $payload ) ) { $payload = '{}'; } return "twq('event'," . $code_json . ',' . $payload . ');'; } function x_pixel_printed_conversion_ids( $conversion_id = '' ) { static $ids = array(); if ( is_string( $conversion_id ) && $conversion_id !== '' && ! in_array( $conversion_id, $ids, true ) ) { $ids[] = $conversion_id; } return $ids; } function x_pixel_print_event_script( $code, $params ) { $script = x_pixel_event_script( $code, $params ); if ( $script === '' ) { return; } if ( is_array( $params ) && isset( $params['conversion_id'] ) ) { x_pixel_printed_conversion_ids( $params['conversion_id'] ); } wp_print_inline_script_tag( $script ); } function x_pixel_take_queued_events() { $events = array(); foreach ( x_pixel_sessions() as $session ) { $queued = $session->get( 'x_pixel_queue', array() ); if ( ! is_array( $queued ) || $queued === array() ) { continue; } $session->set( 'x_pixel_queue', array() ); foreach ( $queued as $event ) { if ( empty( $event['code'] ) || ! is_string( $event['code'] ) ) { continue; } $events[] = array( 'code' => $event['code'], 'params' => isset( $event['params'] ) && is_array( $event['params'] ) ? $event['params'] : array(), ); } } return $events; } function x_pixel_flush_queued_events() { if ( is_admin() ) { return; } foreach ( x_pixel_take_queued_events() as $event ) { x_pixel_print_event_script( $event['code'], $event['params'] ); } } function x_pixel_url_host( $url ) { $parts = wp_parse_url( (string) $url ); if ( empty( $parts['host'] ) ) { return ''; } $host = strtolower( $parts['host'] ); if ( ! empty( $parts['port'] ) ) { $host .= ':' . (int) $parts['port']; } return $host; } function x_pixel_is_same_origin_request() { if ( ! isset( $_SERVER['REQUEST_METHOD'] ) || $_SERVER['REQUEST_METHOD'] !== 'POST' ) { return false; } $request_host = isset( $_SERVER['HTTP_HOST'] ) ? strtolower( sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ) ) : ''; if ( $request_host === '' ) { return false; } if ( isset( $_SERVER['HTTP_SEC_FETCH_SITE'] ) ) { return sanitize_text_field( wp_unslash( $_SERVER['HTTP_SEC_FETCH_SITE'] ) ) === 'same-origin'; } if ( isset( $_SERVER['HTTP_ORIGIN'] ) ) { return x_pixel_url_host( esc_url_raw( wp_unslash( $_SERVER['HTTP_ORIGIN'] ) ) ) === $request_host; } $referer = wp_get_raw_referer(); return $referer && x_pixel_url_host( $referer ) === $request_host; } function x_pixel_no_store_headers( $headers ) { $headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0, private'; return $headers; } function x_pixel_ajax_drain() { add_filter( 'nocache_headers', 'x_pixel_no_store_headers', 100 ); nocache_headers(); if ( ! x_pixel_is_same_origin_request() ) { wp_send_json( array(), 403, x_pixel_json_flags() ); } wp_send_json( x_pixel_take_queued_events(), 200, x_pixel_json_flags() ); } add_action( 'wp_ajax_x_pixel_drain', 'x_pixel_ajax_drain' ); add_action( 'wp_ajax_nopriv_x_pixel_drain', 'x_pixel_ajax_drain' ); function x_pixel_print_drain_script() { if ( is_admin() || x_pixel_get_id() === '' ) { return; } $woocommerce = class_exists( 'WooCommerce' ); $edd = function_exists( 'EDD' ); if ( ! $woocommerce && ! $edd ) { return; } $config = wp_json_encode( array( 'url' => admin_url( 'admin-ajax.php', 'relative' ), 'wc' => $woocommerce, 'edd' => $edd, 'atc' => get_option( X_PIXEL_OPTION_EVENT_ATC, '' ) !== '', 'fired' => x_pixel_printed_conversion_ids(), 'cookies' => x_pixel_session_cookie_names(), 'prefixes' => x_pixel_session_cookie_prefixes(), ), x_pixel_json_flags() ); if ( ! is_string( $config ) ) { return; } $listener = <<<'JS' (function (c) { var timer = null; var fired = window.__xPixelFired = window.__xPixelFired || new Set(); for (var f = 0; f < c.fired.length; f++) { fired.add(c.fired[f]); } function fire(events) { if (!window.twq || !Array.isArray(events)) { return; } for (var i = 0; i < events.length; i++) { var event = events[i] || {}; var params = event.params && typeof event.params === 'object' ? event.params : {}; var id = params.conversion_id; if (typeof id === 'string' && id !== '') { if (fired.has(id)) { continue; } fired.add(id); } twq('event', event.code, params); } } function hasSession() { var cookies = []; try { cookies = document.cookie ? document.cookie.split(';') : []; } catch (e) { return false; } for (var i = 0; i < cookies.length; i++) { var name = cookies[i].replace(/^\s+/, '').split('=')[0]; if (c.cookies.indexOf(name) !== -1) { return true; } for (var p = 0; p < c.prefixes.length; p++) { if (name.indexOf(c.prefixes[p]) === 0) { return true; } } } return false; } function drain() { if (!window.fetch) { return; } clearTimeout(timer); timer = setTimeout(function () { fetch(c.url, { method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: 'action=x_pixel_drain' }).then(function (r) { return r.ok ? r.json() : []; }).then(fire).catch(function () {}); }, 250); } function ready(fn) { if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', fn); } else { fn(); } } ready(function () { if (hasSession()) { drain(); } }); if (!c.atc) { return; } if (c.wc) { document.addEventListener('wc-blocks_added_to_cart', drain); ready(function () { if (window.jQuery) { jQuery(document.body).on('added_to_cart', function (e, fragments) { var events = fragments && fragments.x_pixel_events; if (Array.isArray(events) && events.length) { fire(events); } else { drain(); } }); } if (!window.wp || !wp.data || !wp.data.subscribe) { return; } var lastCount = null; wp.data.subscribe(function () { var store = wp.data.select('wc/store/cart'); if (!store || !store.getCartData) { return; } if (store.hasFinishedResolution && !store.hasFinishedResolution('getCartData')) { return; } var data = store.getCartData(); var count = data && data.itemsCount; if (typeof count !== 'number') { return; } if (lastCount !== null && count > lastCount) { drain(); } lastCount = count; }, 'wc/store/cart'); }); } if (c.edd) { ready(function () { if (window.jQuery) { jQuery(document.body).on('edd_cart_item_added', drain); } }); } }) JS; wp_print_inline_script_tag( $listener . '(' . $config . ');' ); }