Plugin Directory

Changeset 3420138


Ignore:
Timestamp:
12/15/2025 12:46:42 PM (3 months ago)
Author:
alekv
Message:

releasing version 1.54.0

Location:
woocommerce-google-adwords-conversion-tracking-tag/trunk
Files:
8 added
8 deleted
29 edited

Legend:

Unmodified
Added
Removed
  • woocommerce-google-adwords-conversion-tracking-tag/trunk/css/admin.css

    r3415018 r3420138  
    393393}
    394394
     395.pmw .opportunity-card-top-impact-level.impact-high,
     396.pmw .notification-card-top-impact-level.impact-high {
     397    background: #fde8e8;
     398    border-color: #f56565;
     399    color: #c53030;
     400}
     401
     402.pmw .opportunity-card-top-impact-level.impact-medium,
     403.pmw .notification-card-top-impact-level.impact-medium {
     404    background: #fef3c7;
     405    border-color: #f6ad55;
     406    color: #c05621;
     407}
     408
     409.pmw .opportunity-card-top-impact-level.impact-low,
     410.pmw .notification-card-top-impact-level.impact-low {
     411    background: #e6fffa;
     412    border-color: #48bb78;
     413    color: #276749;
     414}
     415
    395416.pmw .opportunity-card-middle,
    396417.pmw .notification-card-middle {
  • woocommerce-google-adwords-conversion-tracking-tag/trunk/includes/admin/class-admin.php

    r3415018 r3420138  
    377377            esc_html__( 'Hotjar site ID', 'woocommerce-google-adwords-conversion-tracking-tag' ),
    378378            [__CLASS__, 'option_html_hotjar_site_id'],
     379            'wpm_plugin_options_page',
     380            $section_ids['settings_name']
     381        );
     382        // add the field for the Contentsquare pixel
     383        add_settings_field(
     384            'pmw_plugin_contentsquare_tag_id',
     385            esc_html__( 'Contentsquare tag ID', 'woocommerce-google-adwords-conversion-tracking-tag' ) . self::html_beta(),
     386            [__CLASS__, 'option_html_contentsquare_tag_id'],
    379387            'wpm_plugin_options_page',
    380388            $section_ids['settings_name']
     
    426434         */
    427435        if ( wpm_fs()->can_use_premium_code__premium_only() || Options::is_pro_version_demo_active() ) {
    428             if ( Helpers::is_experiment() ) {
    429                 // Add the field for the Adroll advertiser ID
    430                 add_settings_field(
    431                     'pmw_adroll_advertiser_id',
    432                     esc_html__( 'Adroll advertiser ID', 'woocommerce-google-adwords-conversion-tracking-tag' ) . self::html_beta(),
    433                     [__CLASS__, 'option_html_adroll_advertiser_id'],
    434                     'wpm_plugin_options_page',
    435                     $section_ids['settings_name']
    436                 );
    437                 // Add the field for the Adroll pixel ID
    438                 add_settings_field(
    439                     'pmw_adroll_pixel_id',
    440                     esc_html__( 'Adroll pixel ID', 'woocommerce-google-adwords-conversion-tracking-tag' ) . self::html_beta(),
    441                     [__CLASS__, 'option_html_adroll_pixel_id'],
    442                     'wpm_plugin_options_page',
    443                     $section_ids['settings_name']
    444                 );
    445             }
     436            // Add the field for the Adroll advertiser ID
     437            add_settings_field(
     438                'pmw_adroll_advertiser_id',
     439                esc_html__( 'Adroll advertiser ID', 'woocommerce-google-adwords-conversion-tracking-tag' ) . self::html_beta(),
     440                [__CLASS__, 'option_html_adroll_advertiser_id'],
     441                'wpm_plugin_options_page',
     442                $section_ids['settings_name']
     443            );
     444            // Add the field for the Adroll pixel ID
     445            add_settings_field(
     446                'pmw_adroll_pixel_id',
     447                esc_html__( 'Adroll pixel ID', 'woocommerce-google-adwords-conversion-tracking-tag' ) . self::html_beta(),
     448                [__CLASS__, 'option_html_adroll_pixel_id'],
     449                'wpm_plugin_options_page',
     450                $section_ids['settings_name']
     451            );
    446452            // Add the field for the LinkedIn partner ID
    447453            add_settings_field(
     
    460466                $section_ids['settings_name']
    461467            );
    462             if ( Helpers::is_experiment() ) {
    463                 // add the field for the Outbrain pixel
    464                 add_settings_field(
    465                     'pmw_plugin_outbrain_advertiser_id',
    466                     esc_html__( 'Outbrain advertiser ID', 'woocommerce-google-adwords-conversion-tracking-tag' ) . self::html_beta(),
    467                     [__CLASS__, 'option_html_outbrain_advertiser_id'],
    468                     'wpm_plugin_options_page',
    469                     $section_ids['settings_name']
    470                 );
    471             }
     468            // add the field for the Outbrain pixel
     469            add_settings_field(
     470                'pmw_plugin_outbrain_advertiser_id',
     471                esc_html__( 'Outbrain advertiser ID', 'woocommerce-google-adwords-conversion-tracking-tag' ) . self::html_beta(),
     472                [__CLASS__, 'option_html_outbrain_advertiser_id'],
     473                'wpm_plugin_options_page',
     474                $section_ids['settings_name']
     475            );
    472476            // Add the field for the Pinterest pixel
    473477            add_settings_field(
     
    11261130        ];
    11271131        self::add_subsection_div( $section_ids, $sub_section_ids );
    1128         // Add field for the LinkedIn search event
    1129         add_settings_field(
    1130             'pmw_setting_linkedin_search',
    1131             esc_html__( 'Search event ID', 'woocommerce-google-adwords-conversion-tracking-tag' ),
    1132             [__CLASS__, 'setting_linkedin_search'],
    1133             'wpm_plugin_options_page',
    1134             $section_ids['settings_name']
    1135         );
    11361132        // Add field for the LinkedIn view_content event
    11371133        add_settings_field(
     
    11421138            $section_ids['settings_name']
    11431139        );
    1144         // Add field for the LinkedIn add_to_list event
    1145         add_settings_field(
    1146             'pmw_setting_linkedin_add_to_list',
    1147             esc_html__( 'Add To List event ID', 'woocommerce-google-adwords-conversion-tracking-tag' ),
    1148             [__CLASS__, 'setting_linkedin_add_to_list'],
    1149             'wpm_plugin_options_page',
    1150             $section_ids['settings_name']
    1151         );
    11521140        // Add field for the LinkedIn add_to_cart event
    11531141        add_settings_field(
     
    11551143            esc_html__( 'Add-to-cart event ID', 'woocommerce-google-adwords-conversion-tracking-tag' ),
    11561144            [__CLASS__, 'setting_linkedin_add_to_cart'],
    1157             'wpm_plugin_options_page',
    1158             $section_ids['settings_name']
    1159         );
    1160         // Add field for the LinkedIn start_checkout event
    1161         add_settings_field(
    1162             'pmw_setting_linkedin_start_checkout',
    1163             esc_html__( 'Start-checkout event ID', 'woocommerce-google-adwords-conversion-tracking-tag' ),
    1164             [__CLASS__, 'setting_linkedin_start_checkout'],
    11651145            'wpm_plugin_options_page',
    11661146            $section_ids['settings_name']
     
    27942774    }
    27952775
     2776    public static function option_html_contentsquare_tag_id() {
     2777        ?>
     2778        <input class="pmw mono"
     2779               id="pmw_plugin_contentsquare_tag_id"
     2780               name="wgact_plugin_options[pixels][contentsquare][tag_id]"
     2781               size="40"
     2782               type="text"
     2783               value="<?php
     2784        echo esc_html( Options::get_contentsquare_tag_id() );
     2785        ?>"
     2786            <?php
     2787        echo esc_html( self::disable_if_demo() );
     2788        ?>
     2789               onclick="this.select();"
     2790        />
     2791        <?php
     2792        self::display_status_icon( Options::is_contentsquare_active() );
     2793        self::get_documentation_html_by_key( 'contentsquare_tag_id' );
     2794        self::html_pro_feature();
     2795        echo '<br><br>';
     2796        esc_html_e( 'The Contentsquare tag ID looks like this:', 'woocommerce-google-adwords-conversion-tracking-tag' );
     2797        echo '&nbsp;<code>b457e22cc0c6e</code>&nbsp;';
     2798    }
     2799
    27962800    public static function option_html_facebook_pixel_id() {
    27972801        ?>
     
    29402944    }
    29412945
    2942     public static function setting_linkedin_search() {
    2943         $text_length = max( strlen( Options::get_linkedin_conversion_id( 'search' ) ), 14 );
    2944         ?>
    2945         <input class="pmw mono"
    2946                id="pmw_setting_linkedin_search"
    2947                name="wgact_plugin_options[pixels][linkedin][conversion_ids][search]"
    2948                size="<?php
    2949         echo esc_html( $text_length );
    2950         ?>"
    2951                type="text"
    2952                value="<?php
    2953         echo esc_html( Options::get_linkedin_conversion_id( 'search' ) );
    2954         ?>"
    2955                style="width:<?php
    2956         echo esc_html( $text_length );
    2957         ?>ch"
    2958             <?php
    2959         echo esc_html( self::disable_if_demo() );
    2960         ?>
    2961                onclick="this.select();"
    2962         />
    2963         <?php
    2964         self::display_status_icon( Options::get_linkedin_conversion_id( 'search' ), Options::is_linkedin_active() );
    2965         self::get_documentation_html_by_key( 'linkedin_event_ids' );
    2966         self::wistia_video_icon( 'zrrp8aq4g0' );
    2967         self::html_pro_feature();
    2968     }
    2969 
    29702946    public static function setting_linkedin_view_content() {
    29712947        $text_length = max( strlen( Options::get_linkedin_conversion_id( 'view_content' ) ), 14 );
     
    29942970        self::wistia_video_icon( 'zrrp8aq4g0' );
    29952971        self::html_pro_feature();
    2996     }
    2997 
    2998     public static function setting_linkedin_add_to_list() {
    2999         $text_length = max( strlen( Options::get_linkedin_conversion_id( 'add_to_list' ) ), 14 );
    3000         ?>
    3001         <input class="pmw mono"
    3002                id="pmw_setting_linkedin_add_to_list"
    3003                name="wgact_plugin_options[pixels][linkedin][conversion_ids][add_to_list]"
    3004                size="<?php
    3005         echo esc_html( $text_length );
    3006         ?>"
    3007                type="text"
    3008                value="<?php
    3009         echo esc_html( Options::get_linkedin_conversion_id( 'add_to_list' ) );
    3010         ?>"
    3011                style="width:<?php
    3012         echo esc_html( $text_length );
    3013         ?>ch"
    3014             <?php
    3015         echo esc_html( self::disable_if_demo() );
    3016         ?>
    3017                onclick="this.select();"
    3018         />
    3019         <?php
    3020         self::display_status_icon( Options::get_linkedin_conversion_id( 'add_to_list' ), Options::is_linkedin_active() );
    3021         self::get_documentation_html_by_key( 'linkedin_event_ids' );
    3022         self::wistia_video_icon( 'zrrp8aq4g0' );
    3023         self::html_pro_feature();
     2972        echo '<br>';
     2973        esc_html_e( 'Map to LinkedIn conversion type:', 'woocommerce-google-adwords-conversion-tracking-tag' );
     2974        echo '&nbsp;<code>key_page_view</code>';
    30242975    }
    30252976
     
    30503001        self::wistia_video_icon( 'zrrp8aq4g0' );
    30513002        self::html_pro_feature();
    3052     }
    3053 
    3054     public static function setting_linkedin_start_checkout() {
    3055         $text_length = max( strlen( Options::get_linkedin_conversion_id( 'start_checkout' ) ), 14 );
    3056         ?>
    3057         <input class="pmw mono"
    3058                id="pmw_setting_linkedin_start_checkout"
    3059                name="wgact_plugin_options[pixels][linkedin][conversion_ids][start_checkout]"
    3060                size="<?php
    3061         echo esc_html( $text_length );
    3062         ?>"
    3063                type="text"
    3064                value="<?php
    3065         echo esc_html( Options::get_linkedin_conversion_id( 'start_checkout' ) );
    3066         ?>"
    3067                style="width:<?php
    3068         echo esc_html( $text_length );
    3069         ?>ch"
    3070             <?php
    3071         echo esc_html( self::disable_if_demo() );
    3072         ?>
    3073                onclick="this.select();"
    3074         />
    3075         <?php
    3076         self::display_status_icon( Options::get_linkedin_conversion_id( 'start_checkout' ), Options::is_linkedin_active() );
    3077         self::get_documentation_html_by_key( 'linkedin_event_ids' );
    3078         self::wistia_video_icon( 'zrrp8aq4g0' );
    3079         self::html_pro_feature();
     3003        echo '<br>';
     3004        esc_html_e( 'Map to LinkedIn conversion type:', 'woocommerce-google-adwords-conversion-tracking-tag' );
     3005        echo '&nbsp;<code>add_to_cart</code>';
    30803006    }
    30813007
     
    31063032        self::wistia_video_icon( 'zrrp8aq4g0' );
    31073033        self::html_pro_feature();
     3034        echo '<br>';
     3035        esc_html_e( 'Map to LinkedIn conversion type:', 'woocommerce-google-adwords-conversion-tracking-tag' );
     3036        echo '&nbsp;<code>purchase</code>';
    31083037    }
    31093038
  • woocommerce-google-adwords-conversion-tracking-tag/trunk/includes/admin/class-debug-info.php

    r3308972 r3420138  
    4040            $html .= 'WordPress memory limit:    ' . Environment::get_wp_memory_limit() . PHP_EOL;
    4141            $curl_available = ( Environment::is_curl_active() ? 'yes' : 'no' );
    42             $html .= 'curl available:            ' . $curl_available . PHP_EOL;
    43             $transients_enabled = ( Environment::is_transients_enabled() ? 'yes' : 'no' );
    44             $html .= 'transients enabled:        ' . $transients_enabled . PHP_EOL;
     42            $html .= 'curl available:                            ' . $curl_available . PHP_EOL;
     43            $transients_enabled = Environment::is_transients_enabled();
     44            $transients_warning = ( $transients_enabled ? '' : ' <--------- !!!!! TRANSIENTS DISABLED !!!!!' );
     45            $html .= 'Transients enabled:                        ' . (( $transients_enabled ? 'yes' : 'no' )) . $transients_warning . PHP_EOL;
     46            $external_object_cache = Environment::get_external_object_cache();
     47            $html .= 'External object cache (Redis/Memcached):   ' . $external_object_cache . PHP_EOL;
    4548            $html .= PHP_EOL;
    4649            $html .= 'wp_remote_get to Cloudflare:           ' . self::pmw_remote_get_response( 'https://www.cloudflare.com/cdn-cgi/trace' ) . PHP_EOL;
     
    250253            $maximum_orders_to_analyze
    251254         );
    252         set_transient( 'pmw_tracking_accuracy_analysis_running', true );
    253         set_transient( 'pmw_tracking_accuracy_analysis_max_orders', $maximum_orders_to_analyze );
     255        // Set the running lock with a 30-minute expiration to prevent permanent locks
     256        // if the analysis crashes or times out. This is especially important with
     257        // external object caches (Redis/Memcached) where transients without expiration
     258        // can behave unexpectedly.
     259        set_transient( 'pmw_tracking_accuracy_analysis_running', true, 30 * MINUTE_IN_SECONDS );
     260        // Store max orders with expiration to match the analysis data lifecycle
     261        set_transient( 'pmw_tracking_accuracy_analysis_max_orders', $maximum_orders_to_analyze, MONTH_IN_SECONDS );
    254262        return $maximum_orders_to_analyze;
    255263    }
     
    339347            ];
    340348        }
    341         set_transient( 'pmw_tracking_accuracy_analysis', $analysis, MONTH_IN_SECONDS );
     349        self::set_transient_with_verification( 'pmw_tracking_accuracy_analysis', $analysis, MONTH_IN_SECONDS );
    342350    }
    343351
     
    392400            return $b['order_count_total'] - $a['order_count_total'];
    393401        } );
    394         set_transient( 'pmw_tracking_accuracy_analysis_weighted', $analysis, MONTH_IN_SECONDS );
     402        self::set_transient_with_verification( 'pmw_tracking_accuracy_analysis_weighted', $analysis, MONTH_IN_SECONDS );
    395403    }
    396404
     
    666674            $tracked_payment_methods = $wpdb->get_col( "SELECT DISTINCT meta_value FROM {$wpdb->prefix}postmeta WHERE `meta_key` = '_payment_method' AND meta_value != ''" );
    667675        }
    668         set_transient( 'pmw_tracked_payment_methods', $tracked_payment_methods, MONTH_IN_SECONDS );
     676        self::set_transient_with_verification( 'pmw_tracked_payment_methods', $tracked_payment_methods, MONTH_IN_SECONDS );
    669677    }
    670678
     
    680688    }
    681689
     690    /**
     691     * Set a transient with verification that it was stored correctly.
     692     *
     693     * This is important for sites using external object caches (Redis/Memcached)
     694     * where transients might fail to store due to:
     695     * - Memory limits being exceeded
     696     * - Data size limits per key
     697     * - Cache eviction policies
     698     * - Serialization issues with complex data
     699     *
     700     * If verification fails, we log the error for debugging purposes.
     701     *
     702     * @param string $transient  Transient name.
     703     * @param mixed  $value      Transient value.
     704     * @param int    $expiration Time until expiration in seconds.
     705     *
     706     * @return bool True if the transient was set and verified, false otherwise.
     707     *
     708     * @since 1.47.0
     709     */
     710    private static function set_transient_with_verification( $transient, $value, $expiration ) {
     711        // Attempt to set the transient
     712        $result = set_transient( $transient, $value, $expiration );
     713        if ( !$result ) {
     714            Logger::debug( 'Failed to set transient: ' . $transient );
     715            return false;
     716        }
     717        // Verify the transient was actually stored by reading it back
     718        $stored_value = get_transient( $transient );
     719        if ( false === $stored_value ) {
     720            Logger::debug( sprintf( 'Transient verification failed for %s. External object cache (Redis/Memcached) may have rejected the data. Cache type: %s', $transient, Environment::get_external_object_cache() ) );
     721            return false;
     722        }
     723        // For arrays, verify the count matches as a sanity check
     724        // This helps detect partial data corruption
     725        if ( is_array( $value ) && is_array( $stored_value ) ) {
     726            if ( count( $value ) !== count( $stored_value ) ) {
     727                Logger::debug( sprintf(
     728                    'Transient data mismatch for %s. Expected %d items, got %d. Possible data corruption.',
     729                    $transient,
     730                    count( $value ),
     731                    count( $stored_value )
     732                ) );
     733                return false;
     734            }
     735        }
     736        return true;
     737    }
     738
    682739}
  • woocommerce-google-adwords-conversion-tracking-tag/trunk/includes/admin/class-documentation.php

    r3415018 r3420138  
    3535        $documentation_links = [
    3636            'default'                                           => '/docs/wpm/',
    37             'script_blockers'                                   => '/docs/wpm/setup/script-blockers/',
    38             'google_analytics_universal_property'               => '/docs/wpm/plugin-configuration/google-analytics',
    39             'google_analytics_4_id'                             => '/docs/wpm/plugin-configuration/google-analytics#connect-an-existing-google-analytics-4-property',
     37            'acr'                                               => '/docs/wpm/features/acr',
     38            'adroll_advertiser_id'                              => '/docs/wpm/plugin-configuration/adroll#advertiser-id-and-pixel-id',
     39            'adroll_pixel_id'                                   => '/docs/wpm/plugin-configuration/adroll#advertiser-id-and-pixel-id',
     40            'aw_merchant_id'                                    => '/docs/wpm/plugin-configuration/google-ads/#conversion-cart-data',
     41            'bing_enhanced_conversions'                         => '/docs/wpm/plugin-configuration/microsoft-advertising#enhanced-conversions',
     42            'bing_uet_tag_id'                                   => '/docs/wpm/plugin-configuration/microsoft-advertising#setting-up-the-uet-tag',
     43            'custom_thank_you'                                  => '/docs/wpm/troubleshooting/#wc-custom-thank-you',
     44            'duplication_prevention'                            => '/docs/wpm/shop#order-duplication-prevention',
     45            'dynamic_remarketing'                               => '/docs/wpm/plugin-configuration/shop-settings#dynamic-remarketing',
     46            'explicit_consent_mode'                             => '/docs/wpm/consent-management/overview#explicit-consent-mode',
     47            'facebook_advanced_matching'                        => '/docs/wpm/plugin-configuration/meta#meta-facebook-advanced-matching',
     48            'facebook_capi_token'                               => '/docs/wpm/plugin-configuration/meta/#meta-facebook-conversion-api-capi',
     49            'facebook_domain_verification_id'                   => '/docs/wpm/plugin-configuration/meta#domain-verification',
     50            'facebook_microdata'                                => '/docs/wpm/plugin-configuration/meta#microdata-tags-for-catalogues',
     51            'facebook_microdata_deprecation'                    => '/blog/facebook-microdata-for-catalog-deprecation-notice',
     52            'facebook_pixel_id'                                 => '/docs/wpm/plugin-configuration/meta#find-the-pixel-id',
     53            'ga4_data_api'                                      => '/docs/wpm/plugin-configuration/google-analytics#ga4-data-api',
     54            'ga4_data_api_credentials'                          => '/docs/wpm/plugin-configuration/google-analytics#ga4-data-api-credentials',
     55            'ga4_data_api_property_id'                          => '/docs/wpm/plugin-configuration/google-analytics#ga4-property-id',
     56            'ga4_page_load_time_tracking'                       => '/docs/wpm/plugin-configuration/google-analytics#page-load-time-tracking',
     57            'google_ads_conversion_adjustments'                 => '/docs/wpm/plugin-configuration/google-ads#conversion-adjustments',
    4058            'google_ads_conversion_id'                          => '/docs/wpm/plugin-configuration/google-ads#configure-the-plugin',
    4159            'google_ads_conversion_label'                       => '/docs/wpm/plugin-configuration/google-ads#configure-the-plugin',
    42             'google_optimize_container_id'                      => '/docs/wpm/plugin-configuration/google-optimize',
     60            'google_ads_phone_conversion_label'                 => '/docs/wpm/plugin-configuration/google-ads#phone-conversion-number',
     61            'google_ads_phone_conversion_number'                => '/docs/wpm/plugin-configuration/google-ads#phone-conversion-number',
     62            'google_analytics_4_api_secret'                     => '/docs/wpm/plugin-configuration/google-analytics#ga4-api-secret',
     63            'google_analytics_4_id'                             => '/docs/wpm/plugin-configuration/google-analytics#connect-an-existing-google-analytics-4-property',
     64            'google_analytics_eec'                              => '/docs/wpm/plugin-configuration/google-analytics#enhanced-e-commerce-funnel-setup',
     65            'google_analytics_universal_property'               => '/docs/wpm/plugin-configuration/google-analytics',
     66            'google_consent_mode'                               => '/docs/wpm/consent-management/google#google-consent-mode',
     67            'google_enhanced_conversions'                       => '/docs/wpm/plugin-configuration/google-ads#enhanced-conversions',
     68            'google_gtag_deactivation'                          => '/docs/wpm/faq/#google-tag-assistant-reports-multiple-installations-of-global-site-tag-gtagjs-detected-what-shall-i-do',
    4369            'google_optimize_anti_flicker'                      => '/docs/wpm/plugin-configuration/google-optimize#anti-flicker-snippet',
    4470            'google_optimize_anti_flicker_timeout'              => '/docs/wpm/plugin-configuration/google-optimize#adjusting-the-anti-flicker-snippet-timeout',
    45             'facebook_pixel_id'                                 => '/docs/wpm/plugin-configuration/meta#find-the-pixel-id',
    46             'bing_uet_tag_id'                                   => '/docs/wpm/plugin-configuration/microsoft-advertising#setting-up-the-uet-tag',
    47             'twitter_pixel_id'                                  => '/docs/wpm/plugin-configuration/twitter#pixel-id',
    48             'twitter_event_ids'                                 => '/docs/wpm/plugin-configuration/twitter#event-setup',
     71            'google_optimize_container_id'                      => '/docs/wpm/plugin-configuration/google-optimize',
     72            'google_tag_gateway_measurement_path'               => '/docs/wpm/plugin-configuration/google#google-tag-gateway-for-advertisers',
     73            'google_tag_id'                                     => '/docs/wpm/plugin-configuration/google#google-tag-gateway-for-advertisers',
     74            'google_tcf_support'                                => '/docs/wpm/consent-management/google#google-tcf-support',
     75            'hotjar_site_id'                                    => '/docs/wpm/plugin-configuration/hotjar#hotjar-site-id',
     76            'lazy_load_pmw'                                     => '/docs/wpm/plugin-configuration/general-settings#lazy-load-the-pixel-manager',
     77            'license_expired_warning'                           => '/docs/wpm/license-management#expired-license-warning',
     78            'linkedin_partner_id'                               => '/docs/wpm/plugin-configuration/linkedin#partner-id',
     79            'linkedin_event_ids'                                => '/docs/wpm/plugin-configuration/linkedin#event-setup',
     80            'litespeed-cache-inline-javascript-after-dom-ready' => '/docs/wpm/troubleshooting',
     81            'load_deprecated_functions'                         => '/docs/wpm/plugin-configuration/general-settings#load-deprecated-functions',
     82            'log_files'                                         => '/docs/wpm/developers/logs#accessing-log-files',
     83            'log_http_requests'                                 => '/docs/wpm/developers/logs#log-http-requests',
     84            'log_level'                                         => '/docs/wpm/developers/logs#log-levels',
     85            'logger_activation'                                 => '/docs/wpm/developers/logs#logger-activation',
     86            'ltv_order_calculation'                             => '/docs/wpm/plugin-configuration/shop-settings#active-lifetime-value-calculation',
     87            'ltv_recalculation'                                 => '/docs/wpm/plugin-configuration/shop-settings#lifetime-value-recalculation',
     88            'marketing_value_logic'                             => '/docs/wpm/plugin-configuration/shop-settings#marketing-value-logic',
     89            'marketing_value_profit_margin'                     => '/docs/wpm/plugin-configuration/shop-settings#profit-margin',
     90            'marketing_value_subtotal'                          => '/docs/wpm/plugin-configuration/shop-settings#order-subtotal-default',
     91            'marketing_value_total'                             => '/docs/wpm/plugin-configuration/shop-settings#order-total',
     92            'maximum_compatibility_mode'                        => '/docs/wpm/plugin-configuration/general-settings/#maximum-compatibility-mode',
     93            'microsoft_ads_consent_mode'                        => '/docs/wpm/consent-management/microsoft#microsoft-ads-consent-mode',
     94            'opportunity_google_ads_conversion_adjustments'     => '/docs/wpm/opportunities#google-ads-conversion-adjustments',
     95            'opportunity_google_enhanced_conversions'           => '/docs/wpm/opportunities#google-ads-enhanced-conversions',
     96            'order_extra_details'                               => '/docs/wpm/plugin-configuration/shop-settings#extra-order-data-output',
     97            'order_list_info'                                   => '/docs/wpm/diagnostics#order-list-info',
     98            'order_modal_ltv'                                   => '/docs/wpm/shop#lifetime-value',
     99            'outbrain_advertiser_id'                            => '/docs/wpm/plugin-configuration/outbrain',
     100            'pageview_events_s2s'                               => '/docs/wpm/plugin-configuration/general-settings#track-pageview-events-server-to-server',
     101            'payment-gateways'                                  => '/docs/wpm/setup/requirements#payment-gateways',
     102            'payment_gateway_tracking_accuracy'                 => '/docs/wpm/diagnostics/#payment-gateway-tracking-accuracy-report',
     103            'pinterest_ad_account_id'                           => '/docs/wpm/plugin-configuration/pinterest#ad-account-id',
     104            'pinterest_advanced_matching'                       => '/docs/wpm/plugin-configuration/pinterest#advanced-matching',
     105            'pinterest_apic_token'                              => '/docs/wpm/plugin-configuration/pinterest#api-for-conversions-token',
     106            'pinterest_enhanced_match'                          => '/docs/wpm/plugin-configuration/pinterest#enhanced-match',
    49107            'pinterest_pixel_id'                                => '/docs/wpm/plugin-configuration/pinterest',
     108            'reddit_advanced_matching'                          => '/docs/wpm/plugin-configuration/reddit#advanced-matching',
     109            'reddit_advertiser_id'                              => '/docs/wpm/plugin-configuration/reddit#setup-instruction',
     110            'reddit_capi_test_event_code'                       => '/docs/wpm/plugin-configuration/reddit#testing',
     111            'reddit_capi_token'                                 => '/docs/wpm/plugin-configuration/reddit#conversions-api-capi',
     112            'restricted_consent_regions'                        => '/docs/wpm/consent-management/overview#explicit-consent-regions',
     113            'script_blockers'                                   => '/docs/wpm/setup/script-blockers/',
     114            'scroll_tracker_threshold'                          => '/docs/wpm/plugin-configuration/general-settings/#scroll-tracker',
     115            'snapchat_advanced_matching'                        => '/docs/wpm/plugin-configuration/snapchat#advanced-matching',
     116            'snapchat_capi_token'                               => '/docs/wpm/plugin-configuration/snapchat#conversions-api',
    50117            'snapchat_pixel_id'                                 => '/docs/wpm/plugin-configuration/snapchat',
    51             'snapchat_capi_token'                               => '/docs/wpm/plugin-configuration/snapchat#conversions-api',
    52             'snapchat_advanced_matching'                        => '/docs/wpm/plugin-configuration/snapchat#advanced-matching',
    53             'tiktok_pixel_id'                                   => '/docs/wpm/plugin-configuration/tiktok',
     118            'subscription_value_multiplier'                     => '/docs/wpm/plugin-configuration/shop-settings#subscription-value-multiplier',
     119            'taboola_account_id'                                => '/docs/wpm/plugin-configuration/taboola',
     120            'test_order'                                        => '/docs/wpm/testing#test-order',
     121            'the_dismiss_button_doesnt_work_why'                => '/docs/wpm/faq/#the-dismiss-button-doesnt-work-why',
    54122            'tiktok_advanced_matching'                          => '/docs/wpm/plugin-configuration/tiktok#advanced-matching',
    55123            'tiktok_eapi_token'                                 => '/docs/wpm/plugin-configuration/tiktok#access-token',
     124            'tiktok_pixel_id'                                   => '/docs/wpm/plugin-configuration/tiktok',
     125            'twitter_event_ids'                                 => '/docs/wpm/plugin-configuration/twitter#event-setup',
     126            'twitter_pixel_id'                                  => '/docs/wpm/plugin-configuration/twitter#pixel-id',
     127            'variations_output'                                 => '/docs/wpm/plugin-configuration/shop-settings#dynamic-remarketing',
    56128            'vwo_account_id'                                    => '/docs/wpm/plugin-configuration/vwo',
    57             'hotjar_site_id'                                    => '/docs/wpm/plugin-configuration/hotjar#hotjar-site-id',
    58             'google_gtag_deactivation'                          => '/docs/wpm/faq/#google-tag-assistant-reports-multiple-installations-of-global-site-tag-gtagjs-detected-what-shall-i-do',
    59             'google_consent_mode'                               => '/docs/wpm/consent-management/google#google-consent-mode',
    60             'restricted_consent_regions'                        => '/docs/wpm/consent-management/overview#explicit-consent-regions',
    61             'google_analytics_eec'                              => '/docs/wpm/plugin-configuration/google-analytics#enhanced-e-commerce-funnel-setup',
    62             'google_analytics_4_api_secret'                     => '/docs/wpm/plugin-configuration/google-analytics#ga4-api-secret',
    63             'google_enhanced_conversions'                       => '/docs/wpm/plugin-configuration/google-ads#enhanced-conversions',
    64             'google_ads_phone_conversion_number'                => '/docs/wpm/plugin-configuration/google-ads#phone-conversion-number',
    65             'google_ads_phone_conversion_label'                 => '/docs/wpm/plugin-configuration/google-ads#phone-conversion-number',
    66             'explicit_consent_mode'                             => '/docs/wpm/consent-management/overview#explicit-consent-mode',
    67             'facebook_capi_token'                               => '/docs/wpm/plugin-configuration/meta/#meta-facebook-conversion-api-capi',
    68             'facebook_advanced_matching'                        => '/docs/wpm/plugin-configuration/meta#meta-facebook-advanced-matching',
    69             'facebook_microdata'                                => '/docs/wpm/plugin-configuration/meta#microdata-tags-for-catalogues',
    70             'maximum_compatibility_mode'                        => '/docs/wpm/plugin-configuration/general-settings/#maximum-compatibility-mode',
    71             'dynamic_remarketing'                               => '/docs/wpm/plugin-configuration/shop-settings#dynamic-remarketing',
    72             'variations_output'                                 => '/docs/wpm/plugin-configuration/shop-settings#dynamic-remarketing',
    73             'aw_merchant_id'                                    => '/docs/wpm/plugin-configuration/google-ads/#conversion-cart-data',
    74             'custom_thank_you'                                  => '/docs/wpm/troubleshooting/#wc-custom-thank-you',
    75             'the_dismiss_button_doesnt_work_why'                => '/docs/wpm/faq/#the-dismiss-button-doesnt-work-why',
    76129            'wp-rocket-javascript-concatenation'                => '/docs/wpm/troubleshooting',
    77             'litespeed-cache-inline-javascript-after-dom-ready' => '/docs/wpm/troubleshooting',
    78             'payment-gateways'                                  => '/docs/wpm/setup/requirements#payment-gateways',
    79             'test_order'                                        => '/docs/wpm/testing#test-order',
    80             'payment_gateway_tracking_accuracy'                 => '/docs/wpm/diagnostics/#payment-gateway-tracking-accuracy-report',
    81             'acr'                                               => '/docs/wpm/features/acr',
    82             'order_list_info'                                   => '/docs/wpm/diagnostics#order-list-info',
    83             'marketing_value_logic'                             => '/docs/wpm/plugin-configuration/shop-settings#marketing-value-logic',
    84             'marketing_value_subtotal'                          => '/docs/wpm/plugin-configuration/shop-settings#order-subtotal-default',
    85             'marketing_value_total'                             => '/docs/wpm/plugin-configuration/shop-settings#order-total',
    86             'marketing_value_profit_margin'                     => '/docs/wpm/plugin-configuration/shop-settings#profit-margin',
    87             'scroll_tracker_threshold'                          => '/docs/wpm/plugin-configuration/general-settings/#scroll-tracker',
    88             'google_ads_conversion_adjustments'                 => '/docs/wpm/plugin-configuration/google-ads#conversion-adjustments',
    89             'ga4_data_api'                                      => '/docs/wpm/plugin-configuration/google-analytics#ga4-data-api',
    90             'ga4_data_api_property_id'                          => '/docs/wpm/plugin-configuration/google-analytics#ga4-property-id',
    91             'ga4_data_api_credentials'                          => '/docs/wpm/plugin-configuration/google-analytics#ga4-data-api-credentials',
    92             'duplication_prevention'                            => '/docs/wpm/shop#order-duplication-prevention',
    93             'license_expired_warning'                           => '/docs/wpm/license-management#expired-license-warning',
    94             'subscription_value_multiplier'                     => '/docs/wpm/plugin-configuration/shop-settings#subscription-value-multiplier',
    95             'lazy_load_pmw'                                     => '/docs/wpm/plugin-configuration/general-settings#lazy-load-the-pixel-manager',
    96             'opportunity_google_enhanced_conversions'           => '/docs/wpm/opportunities#google-ads-enhanced-conversions',
    97             'opportunity_google_ads_conversion_adjustments'     => '/docs/wpm/opportunities#google-ads-conversion-adjustments',
    98             'ga4_page_load_time_tracking'                       => '/docs/wpm/plugin-configuration/google-analytics#page-load-time-tracking',
    99             'reddit_advertiser_id'                              => '/docs/wpm/plugin-configuration/reddit#setup-instruction',
    100             'reddit_advanced_matching'                          => '/docs/wpm/plugin-configuration/reddit#advanced-matching',
    101             'pinterest_ad_account_id'                           => '/docs/wpm/plugin-configuration/pinterest#ad-account-id',
    102             'pinterest_apic_token'                              => '/docs/wpm/plugin-configuration/pinterest#api-for-conversions-token',
    103             'pinterest_enhanced_match'                          => '/docs/wpm/plugin-configuration/pinterest#enhanced-match',
    104             'pinterest_advanced_matching'                       => '/docs/wpm/plugin-configuration/pinterest#advanced-matching',
    105             'outbrain_advertiser_id'                            => '/docs/wpm/plugin-configuration/outbrain',
    106             'taboola_account_id'                                => '/docs/wpm/plugin-configuration/taboola',
    107             'adroll_advertiser_id'                              => '/docs/wpm/plugin-configuration/adroll#advertiser-id-and-pixel-id',
    108             'adroll_pixel_id'                                   => '/docs/wpm/plugin-configuration/adroll#advertiser-id-and-pixel-id',
    109             'linkedin_partner_id'                               => '/docs/wpm/plugin-configuration/linkedin#partner-id',
    110             'google_tcf_support'                                => '/docs/wpm/consent-management/google#google-tcf-support',
    111             'logger_activation'                                 => '/docs/wpm/developers/logs#logger-activation',
    112             'log_level'                                         => '/docs/wpm/developers/logs#log-levels',
    113             'log_http_requests'                                 => '/docs/wpm/developers/logs#log-http-requests',
    114             'log_files'                                         => '/docs/wpm/developers/logs#accessing-log-files',
    115             'ltv_order_calculation'                             => '/docs/wpm/plugin-configuration/shop-settings#active-lifetime-value-calculation',
    116             'ltv_recalculation'                                 => '/docs/wpm/plugin-configuration/shop-settings#lifetime-value-recalculation',
    117             'order_modal_ltv'                                   => '/docs/wpm/shop#lifetime-value',
    118             'facebook_microdata_deprecation'                    => '/blog/facebook-microdata-for-catalog-deprecation-notice',
    119             'order_extra_details'                               => '/docs/wpm/plugin-configuration/shop-settings#extra-order-data-output',
    120             'microsoft_ads_consent_mode'                        => '/docs/wpm/consent-management/microsoft#microsoft-ads-consent-mode',
    121             'facebook_domain_verification_id'                   => '/docs/wpm/plugin-configuration/meta#domain-verification',
    122             'google_tag_gateway_measurement_path'               => '/docs/wpm/plugin-configuration/google#google-tag-gateway-for-advertisers',
    123             'google_tag_id'                                     => '/docs/wpm/plugin-configuration/google#google-tag-gateway-for-advertisers',
    124             'pageview_events_s2s'                               => '/docs/wpm/plugin-configuration/general-settings#track-pageview-events-server-to-server',
    125             'reddit_capi_token'                                 => '/docs/wpm/plugin-configuration/reddit#conversions-api-capi',
    126             'reddit_capi_test_event_code'                       => '/docs/wpm/plugin-configuration/reddit#testing',
    127             'load_deprecated_functions'                         => '/docs/wpm/plugin-configuration/general-settings#load-deprecated-functions',
    128             'bing_enhanced_conversions'                         => '/docs/wpm/plugin-configuration/microsoft-advertising#enhanced-conversions',
    129130        ];
    130131
  • woocommerce-google-adwords-conversion-tracking-tag/trunk/includes/admin/class-environment.php

    r3396512 r3420138  
    1717    private static $last_order_id      = null;
    1818    private static $last_order         = null;
    19     private static $transients_enabled = null;
     19    private static $transients_enabled    = null;
     20    private static $external_object_cache = null;
    2021
    2122    public static function is_allowed_notification_page( $page = null ) {
     
    17601761    }
    17611762
     1763    /**
     1764     * Get the external object cache type if enabled.
     1765     *
     1766     * Checks for Redis or Memcached object caching.
     1767     *
     1768     * @return string The cache type ('Redis', 'Memcached') or 'no' if not enabled.
     1769     *
     1770     * @since 1.46.0
     1771     */
     1772    public static function get_external_object_cache() {
     1773
     1774        if ( null !== self::$external_object_cache ) {
     1775            return self::$external_object_cache;
     1776        }
     1777
     1778        // Check for Redis
     1779        if (class_exists('Redis')) {
     1780            self::$external_object_cache = 'Redis';
     1781            return self::$external_object_cache;
     1782        }
     1783
     1784        // Check for WP Redis plugin constant
     1785        if (defined('WP_REDIS_DISABLED') && !WP_REDIS_DISABLED) {
     1786            self::$external_object_cache = 'Redis';
     1787            return self::$external_object_cache;
     1788        }
     1789
     1790        // Check for Memcached
     1791        if (class_exists('Memcached') || class_exists('Memcache')) {
     1792            self::$external_object_cache = 'Memcached';
     1793            return self::$external_object_cache;
     1794        }
     1795
     1796        // Check object-cache.php drop-in for Redis or Memcached
     1797        if (file_exists(WP_CONTENT_DIR . '/object-cache.php')) {
     1798            $object_cache_content = file_get_contents(WP_CONTENT_DIR . '/object-cache.php');
     1799            if (stripos($object_cache_content, 'redis') !== false) {
     1800                self::$external_object_cache = 'Redis';
     1801                return self::$external_object_cache;
     1802            }
     1803            if (stripos($object_cache_content, 'memcache') !== false) {
     1804                self::$external_object_cache = 'Memcached';
     1805                return self::$external_object_cache;
     1806            }
     1807        }
     1808
     1809        self::$external_object_cache = 'no';
     1810        return self::$external_object_cache;
     1811    }
     1812
    17621813    public static function is_on_playground_wordpress_net() {
    17631814
  • woocommerce-google-adwords-conversion-tracking-tag/trunk/includes/admin/class-validations.php

    r3409909 r3420138  
    360360
    361361        // Validate LinkedIn conversion IDs
     362        $input = self::validate_linkedin_conversion_id($input, 'view_content');
    362363        $input = self::validate_linkedin_conversion_id($input, 'add_to_cart');
    363         $input = self::validate_linkedin_conversion_id($input, 'start_checkout');
    364364        $input = self::validate_linkedin_conversion_id($input, 'purchase');
    365         $input = self::validate_linkedin_conversion_id($input, 'search');
    366         $input = self::validate_linkedin_conversion_id($input, 'view_content');
    367         $input = self::validate_linkedin_conversion_id($input, 'add_to_list');
    368365
    369366        // validate Outbrain advertiser ID
     
    643640                    : '';
    644641                add_settings_error('wgact_plugin_options', 'invalid-vwo-account-id', esc_html__('You have entered an invalid AB Tasty account ID.', 'woocommerce-google-adwords-conversion-tracking-tag'));
     642            }
     643        }
     644
     645        // Validate the Contentsquare tag ID
     646        if (isset($input['pixels']['contentsquare']['tag_id'])) {
     647
     648            // Trim space, newlines and quotes
     649            $input['pixels']['contentsquare']['tag_id'] = Helpers::trim_string($input['pixels']['contentsquare']['tag_id']);
     650
     651            if (!self::is_contentsquare_tag_id($input['pixels']['contentsquare']['tag_id'])) {
     652                $input['pixels']['contentsquare']['tag_id']
     653                    = Options::get_contentsquare_tag_id()
     654                    ? Options::get_contentsquare_tag_id()
     655                    : '';
     656                add_settings_error('wgact_plugin_options', 'invalid-contentsquare-tag-id', esc_html__('You have entered an invalid Contentsquare tag ID.', 'woocommerce-google-adwords-conversion-tracking-tag'));
    645657            }
    646658        }
     
    10301042    }
    10311043
     1044    public static function is_contentsquare_tag_id( $string ) {
     1045
     1046        // Contentsquare tag ID format: alphanumeric string like b457e22cc0c6e
     1047        $re = '/^[a-z0-9]{10,20}$/m';
     1048
     1049        return self::validate_with_regex($re, $string);
     1050    }
     1051
    10321052    public static function is_scroll_tracker_thresholds( $string ) {
    10331053
  • woocommerce-google-adwords-conversion-tracking-tag/trunk/includes/admin/opportunities/class-opportunities.php

    r3415018 r3420138  
    2222 *            Google Ads Conversion Cart Data
    2323 *
    24  *  TODO: TikTok EAPI
    2524 *  TODO: Newsletter subscription
    2625 *  TODO: Upgrade to Premium version
    27  *  TODO: Gateway accuracy warning
    28  *  TODO: Detect WooCommerce GA Integration (rule, only if one, GA3 or GA4 are enabled)
    2926 *  TODO: Detect MonsterInsights
    3027 *  TODO: Detect Tatvic
     
    8380    private static function opportunities_not_dismissed() {
    8481
     82        $opportunities = [];
     83
    8584        foreach (self::get_opportunities() as $opportunity) {
    8685            if ($opportunity::is_not_dismissed()) {
    87 
    88                 $opportunity::output_card();
    89             }
     86                $opportunities[] = $opportunity;
     87            }
     88        }
     89
     90        // Sort by impact: high first, then medium, then low
     91        $opportunities = self::sort_opportunities_by_impact($opportunities);
     92
     93        foreach ($opportunities as $opportunity) {
     94            $opportunity::output_card();
    9095        }
    9196    }
    9297
    9398    private static function opportunities_dismissed() {
     99
     100        $opportunities = [];
     101
    94102        foreach (self::get_opportunities() as $opportunity) {
    95103            if ($opportunity::is_dismissed()) {
    96                 $opportunity::output_card();
    97             }
    98         }
     104                $opportunities[] = $opportunity;
     105            }
     106        }
     107
     108        // Sort by impact: high first, then medium, then low
     109        $opportunities = self::sort_opportunities_by_impact($opportunities);
     110
     111        foreach ($opportunities as $opportunity) {
     112            $opportunity::output_card();
     113        }
     114    }
     115
     116    /**
     117     * Sort opportunities by impact level (high → medium → low).
     118     *
     119     * @param array $opportunities Array of opportunity class names.
     120     * @return array Sorted array of opportunity class names.
     121     * @since 1.48.0
     122     */
     123    private static function sort_opportunities_by_impact( $opportunities ) {
     124
     125        $impact_order = [
     126            'high'   => 1,
     127            'medium' => 2,
     128            'low'    => 3,
     129        ];
     130
     131        usort($opportunities, function ( $a, $b ) use ( $impact_order ) {
     132            $a_card_data = $a::card_data();
     133            $b_card_data = $b::card_data();
     134
     135            $a_impact = strtolower(isset($a_card_data['impact']) ? $a_card_data['impact'] : 'low');
     136            $b_impact = strtolower(isset($b_card_data['impact']) ? $b_card_data['impact'] : 'low');
     137
     138            $a_order = isset($impact_order[$a_impact]) ? $impact_order[$a_impact] : 4;
     139            $b_order = isset($impact_order[$b_impact]) ? $impact_order[$b_impact] : 4;
     140
     141            return $a_order - $b_order;
     142        });
     143
     144        return $opportunities;
    99145    }
    100146
     
    121167                            <?php esc_html_e('Impact', 'woocommerce-google-adwords-conversion-tracking-tag'); ?>:
    122168                        </div>
    123                         <div class="opportunity-card-top-impact-level">
     169                        <div class="opportunity-card-top-impact-level impact-<?php echo esc_attr(strtolower($card_data['impact'])); ?>">
    124170                            <?php echo esc_html($card_data['impact']); ?>
    125171                        </div>
  • woocommerce-google-adwords-conversion-tracking-tag/trunk/includes/class-geolocation.php

    r3080085 r3420138  
    8080     * Get current user IP Address.
    8181     *
    82      * Source: https://woocommerce.github.io/code-reference/files/woocommerce-includes-class-wc-geolocation.html#source-view.80
     82     * Checks various headers set by CDNs and proxies in order of reliability:
     83     * 1. Cloudflare (CF-Connecting-IP) - Most reliable when behind Cloudflare
     84     * 2. Sucuri (X-Sucuri-ClientIP) - Set by Sucuri WAF
     85     * 3. Akamai/Cloudflare Enterprise (True-Client-IP)
     86     * 4. Incapsula (Incap-Client-IP) - Set by Imperva Incapsula
     87     * 5. Generic proxy headers (X-Real-IP, X-Forwarded-For)
     88     * 6. Direct connection (REMOTE_ADDR) - Fallback
    8389     *
    8490     * @return string
     
    8692    public static function get_ip_address() {
    8793
    88         // If class WC_Geolocation exists, use it to get the IP address
    89         if (class_exists('WC_Geolocation')) {
    90             return \WC_Geolocation::get_ip_address();
     94        /**
     95         * Filter to override server variables for IP detection.
     96         * Useful for testing or custom IP detection logic.
     97         *
     98         * @param array|null $server_override Array of server variables to use instead of actual request data.
     99         *                                    Return null to use the actual request data.
     100         */
     101        $server_override = apply_filters('pmw_geolocation_server_vars', null);
     102
     103        if (null !== $server_override && is_array($server_override)) {
     104            $_server = $server_override;
    91105        } else {
    92             if (isset($_SERVER['HTTP_X_REAL_IP'])) {
    93                 return sanitize_text_field(wp_unslash($_SERVER['HTTP_X_REAL_IP']));
    94             } elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    95                 // Proxy servers can send through this header like this: X-Forwarded-For: client1, proxy1, proxy2
    96                 // Make sure we always only send through the first IP in the list which should always be the client IP.
    97                 return (string) rest_is_ip_address(trim(current(preg_split('/,/', sanitize_text_field(wp_unslash($_SERVER['HTTP_X_FORWARDED_FOR']))))));
    98             } elseif (isset($_SERVER['REMOTE_ADDR'])) {
    99                 return sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR']));
    100             }
    101             return '';
    102         }
     106            $_server = Helpers::get_input_vars(INPUT_SERVER);
     107        }
     108
     109        /**
     110         * Priority order for IP detection headers.
     111         * CDN-specific headers are checked first as they are most reliable.
     112         *
     113         * - HTTP_CF_CONNECTING_IP: Cloudflare's header containing the original visitor IP
     114         * - HTTP_X_SUCURI_CLIENTIP: Sucuri WAF's header for the original client IP
     115         * - HTTP_TRUE_CLIENT_IP: Used by Akamai and Cloudflare Enterprise
     116         * - HTTP_INCAP_CLIENT_IP: Imperva Incapsula's header for the original client IP
     117         * - HTTP_FASTLY_CLIENT_IP: Fastly CDN's header for the original client IP
     118         * - HTTP_X_FORWARDED_FOR: Standard proxy header (may contain multiple IPs), also used by AWS ALB/CloudFront
     119         * - HTTP_X_REAL_IP: Common header set by nginx and other reverse proxies
     120         * - REMOTE_ADDR: Direct connection IP (fallback, may be CDN IP if not configured)
     121         */
     122        $ip_headers = [
     123            'HTTP_CF_CONNECTING_IP',    // Cloudflare
     124            'HTTP_X_SUCURI_CLIENTIP',   // Sucuri WAF
     125            'HTTP_TRUE_CLIENT_IP',      // Akamai / Cloudflare Enterprise
     126            'HTTP_INCAP_CLIENT_IP',     // Imperva Incapsula
     127            'HTTP_FASTLY_CLIENT_IP',    // Fastly CDN
     128            'HTTP_X_FORWARDED_FOR',     // Standard proxy header (AWS ALB/CloudFront also use this)
     129            'HTTP_X_REAL_IP',           // Nginx reverse proxy
     130            'REMOTE_ADDR',              // Direct connection (fallback)
     131        ];
     132
     133        foreach ($ip_headers as $header) {
     134            if (!empty($_server[$header])) {
     135                $ip = sanitize_text_field($_server[$header]);
     136
     137                // X-Forwarded-For can contain multiple IPs: client, proxy1, proxy2
     138                // We want the first one (the original client)
     139                if (false !== strpos($ip, ',')) {
     140                    $ip = trim(explode(',', $ip)[0]);
     141                }
     142
     143                // Validate the IP address
     144                if (filter_var($ip, FILTER_VALIDATE_IP)) {
     145                    self::log_ip_detection($header, $ip, $_server);
     146                    return $ip;
     147                }
     148            }
     149        }
     150
     151        // Note: No logging here - empty IP is expected for health checks, bots, etc.
     152        return '';
     153    }
     154
     155    /**
     156     * Log IP detection details for debugging.
     157     *
     158     * @param string $detected_header The header that provided the IP.
     159     * @param string $ip              The detected IP address.
     160     * @param array  $server          The server variables array.
     161     * @return void
     162     */
     163    private static function log_ip_detection( $detected_header, $ip, $server ) {
     164
     165        // Only log in debug mode to avoid performance impact
     166        if (!Helpers::is_pmw_debug_mode_active()) {
     167            return;
     168        }
     169
     170        // Only log when IP source is not the default REMOTE_ADDR (reduces noise)
     171        if ('REMOTE_ADDR' === $detected_header) {
     172            return;
     173        }
     174
     175        Logger::debug(
     176            sprintf(
     177                'Geolocation: IP detected from %s: %s',
     178                $detected_header,
     179                $ip
     180            )
     181        );
    103182    }
    104183
  • woocommerce-google-adwords-conversion-tracking-tag/trunk/includes/class-options.php

    r3415018 r3420138  
    204204                    'partner_id'     => '',
    205205                    'conversion_ids' => [
    206                         'search'         => '',
    207                         'view_content'   => '',
    208                         'add_to_list'    => '',
    209                         'add_to_cart'    => '',
    210                         'start_checkout' => '',
    211                         'purchase'       => '',
     206                        'view_content' => '',
     207                        'add_to_cart'  => '',
     208                        'purchase'     => '',
    212209                    ],
    213210                ],
     
    231228                'vwo'        => [
    232229                    'account_id' => '',
     230                ],
     231                'contentsquare' => [
     232                    'tag_id' => '',
    233233                ],
    234234            ],
     
    816816
    817817    /**
     818     * Contentsquare
     819     */
     820
     821    public static function get_contentsquare_tag_id() {
     822        return self::get_options_obj()->pixels->contentsquare->tag_id;
     823    }
     824
     825    public static function is_contentsquare_active() {
     826        return (bool) self::get_contentsquare_tag_id();
     827    }
     828
     829    /**
    818830     * Logger
    819831     */
  • woocommerce-google-adwords-conversion-tracking-tag/trunk/includes/pixels/class-pixel-manager.php

    r3415018 r3420138  
    518518    }
    519519
    520     public static function pmw_store_ipv6_in_server_session() {
     520    public static function pmw_store_client_ip_in_server_session() {
    521521        $_post = Helpers::get_input_vars( INPUT_POST );
    522         // return error if the ipv6 field is not set
    523         if ( !isset( $_post['data']['ipv6'] ) ) {
    524             wp_send_json_error( 'No IPv6 address provided' );
    525         }
    526         // return error if the ipv6 field is not a valid IPv6 address
    527         if ( !Helpers::is_valid_ipv6_address( $_post['data']['ipv6'] ) ) {
    528             wp_send_json_error( 'Invalid IPv6 address' );
     522        // return error if the ip field is not set
     523        if ( !isset( $_post['data']['ip'] ) ) {
     524            wp_send_json_error( 'No IP address provided' );
     525        }
     526        $ip = sanitize_text_field( $_post['data']['ip'] );
     527        // return error if the ip field is not a valid IP address (IPv4 or IPv6)
     528        if ( !filter_var( $ip, FILTER_VALIDATE_IP ) ) {
     529            wp_send_json_error( 'Invalid IP address' );
    529530        }
    530531        // If WooCommerce is not active, return error
     
    540541            wp_send_json_error( 'WooCommerce session not available' );
    541542        }
    542         // Set the IPv6 address in the WooCommerce session
    543         WC()->session->set( 'client_ipv6', $_post['data']['ipv6'] );
     543        // Set the client IP address in the WooCommerce session
     544        WC()->session->set( 'client_ip', $ip );
    544545        wp_send_json_success( [
    545             'ipv6'    => $_post['data']['ipv6'],
    546             'message' => 'IPv6 address stored in server session',
     546            'ip'      => $ip,
     547            'message' => 'Client IP address stored in server session',
    547548        ] );
    548549    }
     
    987988        return [
    988989            'site_id' => Options::get_hotjar_site_id(),
     990        ];
     991    }
     992
     993    private static function get_contentsquare_pixel_data() {
     994        return [
     995            'tag_id' => Options::get_contentsquare_tag_id(),
    989996        ];
    990997    }
  • woocommerce-google-adwords-conversion-tracking-tag/trunk/includes/pixels/class-shortcodes.php

    r3313714 r3420138  
    9292            'taboola-event'         => '',
    9393            'tiktok-event'          => 'SubmitForm',
     94            'contentsquare-event'   => '',
    9495        ];
    9596
     
    201202            self::conversion_html_twitter($shortcode_attributes);
    202203        }
     204
     205        // Contentsquare (Premium only)
     206        if (
     207            wpm_fs()->can_use_premium_code__premium_only()
     208            && self::should_tracking_event_be_injected($shortcode_attributes, 'contentsquare')
     209            && Options::is_contentsquare_active()
     210        ) {
     211            self::conversion_html_contentsquare($shortcode_attributes);
     212        }
    203213    }
    204214
     
    225235                },
    226236            );
     237        </script>
     238        <?php
     239    }
     240
     241    private static function conversion_html_contentsquare( $shortcode_attributes ) {
     242
     243        if (empty($shortcode_attributes['contentsquare-event'])) {
     244            return;
     245        }
     246
     247        ?>
     248
     249        <script>
     250            jQuery(document).on("pmw:ready", function () {
     251                if (typeof window._uxa !== "undefined") {
     252                    window._uxa.push(["trackPageEvent", "<?php echo esc_js($shortcode_attributes['contentsquare-event']); ?>"]);
     253                }
     254            });
    227255        </script>
    228256        <?php
  • woocommerce-google-adwords-conversion-tracking-tag/trunk/includes/pixels/google/class-gtg-proxy.php

    r3415018 r3420138  
    33namespace SweetCode\Pixel_Manager\Pixels\Google;
    44
     5use SweetCode\Pixel_Manager\Geolocation;
    56use SweetCode\Pixel_Manager\Helpers;
    67use SweetCode\Pixel_Manager\Logger;
     
    11741175     * Get the real client IP address
    11751176     *
     1177     * Uses the centralized Geolocation class for consistent IP detection
     1178     * across all CDNs and proxies.
     1179     *
    11761180     * @return string The client IP address.
    11771181     */
    11781182    private static function get_client_ip() {
    1179 
    1180         $_server = Helpers::get_input_vars(INPUT_SERVER);
    1181 
    1182         // Check for Cloudflare
    1183         if (!empty($_server['HTTP_CF_CONNECTING_IP'])) {
    1184             return sanitize_text_field($_server['HTTP_CF_CONNECTING_IP']);
    1185         }
    1186 
    1187         // Check for standard forwarded header
    1188         if (!empty($_server['HTTP_X_FORWARDED_FOR'])) {
    1189             $ips = explode(',', $_server['HTTP_X_FORWARDED_FOR']);
    1190             return sanitize_text_field(trim($ips[0]));
    1191         }
    1192 
    1193         // Check for real IP header
    1194         if (!empty($_server['HTTP_X_REAL_IP'])) {
    1195             return sanitize_text_field($_server['HTTP_X_REAL_IP']);
    1196         }
    1197 
    1198         // Fall back to remote addr
    1199         if (!empty($_server['REMOTE_ADDR'])) {
    1200             return sanitize_text_field($_server['REMOTE_ADDR']);
    1201         }
    1202 
    1203         return '';
     1183        return Geolocation::get_ip_address();
    12041184    }
    12051185
  • woocommerce-google-adwords-conversion-tracking-tag/trunk/includes/pixels/google/pmw-gtg-config.json

    r3415018 r3420138  
    77    "log_level": "warning",
    88    "log_directory": "\/Users\/aleksandarvucenovic\/dev\/apps\/wordpress-deployment\/wp-content\/uploads\/pmw-logs",
    9     "updated": 1765263297
     9    "updated": 1765802380
    1010}
  • woocommerce-google-adwords-conversion-tracking-tag/trunk/js/admin/wpm-admin-freemius.p1.min.js.map

    r3374377 r3420138  
    1 {"version":3,"file":"wpm-admin-freemius.p1.min.js","mappings":"2EAAA,WACC,IAEgB,IAAIA,iBAAiB,SAAUC,GAC7CA,EAAUC,QAAQ,SAAUC,GAC3B,GAA+B,UAA3BA,EAASC,cAA2B,CAClBC,OAAOF,EAASG,QAAQC,KAAKJ,EAASC,eACxCI,SAAS,aAC3BH,OAAO,aAAaI,KAAK,sBAAsBC,YAAY,WAE7D,CACD,EACD,GAESC,QAAQN,OAAO,aAAaI,KAAK,sBAAsB,GAAI,CACnEG,YAAY,GAGd,CAAE,MAAOC,GACRC,QAAQD,MAAMA,EACf,CACA,CArBD,E,GCCIE,EAA2B,CAAC,GAGhC,SAASC,EAAoBC,GAE5B,IAAIC,EAAeH,EAAyBE,GAC5C,QAAqBE,IAAjBD,EACH,OAAOA,EAAaE,QAGrB,IAAIC,EAASN,EAAyBE,GAAY,CAGjDG,QAAS,CAAC,GAOX,OAHAE,EAAoBL,GAAUI,EAAQA,EAAOD,QAASJ,GAG/CK,EAAOD,OACf,CCtBAG,CAAQ,G","sources":["webpack://Pixel-Manager-for-WooCommerce/./src/js-src/admin/freemius-keep-deactivate-button-enabled.js","webpack://Pixel-Manager-for-WooCommerce/webpack/bootstrap","webpack://Pixel-Manager-for-WooCommerce/./src/js-src/admin/main-freemius.js"],"sourcesContent":["(function () {\n\ttry {\n\n\t\tlet observer = new MutationObserver(function (mutations) {\n\t\t\tmutations.forEach(function (mutation) {\n\t\t\t\tif (mutation.attributeName === \"class\") {\n\t\t\t\t\tlet attributeValue = jQuery(mutation.target).prop(mutation.attributeName)\n\t\t\t\t\tif (attributeValue.includes(\"disabled\")) {\n\t\t\t\t\t\tjQuery(\".fs-modal\").find(\".button-deactivate\").removeClass(\"disabled\")\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\n\t\tobserver.observe(jQuery(\".fs-modal\").find(\".button-deactivate\")[0], {\n\t\t\tattributes: true,\n\t\t})\n\n\t} catch (error) {\n\t\tconsole.error(error)\n\t}\n})()\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","require(\"./freemius-keep-deactivate-button-enabled\")\n"],"names":["MutationObserver","mutations","forEach","mutation","attributeName","jQuery","target","prop","includes","find","removeClass","observe","attributes","error","console","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","exports","module","__webpack_modules__","require"],"sourceRoot":""}
     1{"version":3,"file":"wpm-admin-freemius.p1.min.js","mappings":"2EAAA,WACC,IAEgB,IAAIA,iBAAiB,SAAUC,GAC7CA,EAAUC,QAAQ,SAAUC,GAC3B,GAA+B,UAA3BA,EAASC,cAA2B,CAClBC,OAAOF,EAASG,QAAQC,KAAKJ,EAASC,eACxCI,SAAS,aAC3BH,OAAO,aAAaI,KAAK,sBAAsBC,YAAY,WAE7D,CACD,EACD,GAESC,QAAQN,OAAO,aAAaI,KAAK,sBAAsB,GAAI,CACnEG,YAAY,GAGd,CAAE,MAAOC,GACRC,QAAQD,MAAMA,EACf,CACA,CArBD,E,GCCIE,EAA2B,CAAC,GAGhC,SAASC,EAAoBC,GAE5B,IAAIC,EAAeH,EAAyBE,GAC5C,QAAqBE,IAAjBD,EACH,OAAOA,EAAaE,QAGrB,IAAIC,EAASN,EAAyBE,GAAY,CAGjDG,QAAS,CAAC,GAOX,OAHAE,EAAoBL,GAAUI,EAAQA,EAAOD,QAASJ,GAG/CK,EAAOD,OACf,CCtBAG,CAAQ,G","sources":["webpack://Pixel-Manager-for-WooCommerce/./src/js-src/admin/freemius-keep-deactivate-button-enabled.js","webpack://Pixel-Manager-for-WooCommerce/webpack/bootstrap","webpack://Pixel-Manager-for-WooCommerce/./src/js-src/admin/main-freemius.js"],"sourcesContent":["(function () {\n\ttry {\n\n\t\tlet observer = new MutationObserver(function (mutations) {\n\t\t\tmutations.forEach(function (mutation) {\n\t\t\t\tif (mutation.attributeName === \"class\") {\n\t\t\t\t\tlet attributeValue = jQuery(mutation.target).prop(mutation.attributeName)\n\t\t\t\t\tif (attributeValue.includes(\"disabled\")) {\n\t\t\t\t\t\tjQuery(\".fs-modal\").find(\".button-deactivate\").removeClass(\"disabled\")\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\n\t\tobserver.observe(jQuery(\".fs-modal\").find(\".button-deactivate\")[0], {\n\t\t\tattributes: true,\n\t\t})\n\n\t} catch (error) {\n\t\tconsole.error(error)\n\t}\n})()\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","require(\"./freemius-keep-deactivate-button-enabled\")\n"],"names":["MutationObserver","mutations","forEach","mutation","attributeName","jQuery","target","prop","includes","find","removeClass","observe","attributes","error","console","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","exports","module","__webpack_modules__","require"],"ignoreList":[],"sourceRoot":""}
  • woocommerce-google-adwords-conversion-tracking-tag/trunk/js/admin/wpm-admin.p1.min.js.map

    r3415018 r3420138  
    1 {"version":3,"file":"wpm-admin.p1.min.js","mappings":"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","sources":["webpack://Pixel-Manager-for-WooCommerce/./src/js-src/admin/script-blocker-warning.js","webpack://Pixel-Manager-for-WooCommerce/./src/js-src/admin/tabs.js","webpack://Pixel-Manager-for-WooCommerce/./src/js-src/admin/helpers.js","webpack://Pixel-Manager-for-WooCommerce/webpack/bootstrap","webpack://Pixel-Manager-for-WooCommerce/./src/js-src/admin/main.js"],"sourcesContent":["function wpm_hide_script_blocker_warning() {\n\tjQuery(\"#script-blocker-notice\").hide()\n}\n\n// try to hide as soon as this script is loaded\n// might be too early in some cases, as the HTML is not rendered yet\nwpm_hide_script_blocker_warning()\n\n// if all other earlier attempts to hide did fail\n// run the function after entire DOM has been loaded\njQuery(function () {\n\twpm_hide_script_blocker_warning()\n})\n","jQuery(function () {\n\n\t// Don't run if we are not one of the\n\t// WPM main tabs\n\tif (\"wpm\" !== wpmGetPageId()) return\n\n\tlet sections    = []\n\tlet subsections = {}\n\n\t// Hide unnecessary elements\n\tjQuery(\".section\").closest(\"tr\").hide()\n\n\t// Collect information on sections\n\tjQuery(\".section\").each(function () {\n\t\tsections.push({\n\t\t\t\"slug\"      : jQuery(this).data(\"sectionSlug\"),\n\t\t\t\"title\"     : jQuery(this).data(\"sectionTitle\"),\n\t\t\t\"badgeCount\": jQuery(this).data(\"badgeCount\") || 0,\n\t\t})\n\t})\n\n\t// Collect information on subsections\n\tjQuery(\".subsection\").each(function () {\n\n\t\tsubsections[jQuery(this).data(\"sectionSlug\")] = subsections[jQuery(this).data(\"sectionSlug\")] || []\n\n\t\tsubsections[jQuery(this).data(\"sectionSlug\")].push({\n\t\t\t\"title\": jQuery(this).data(\"subsectionTitle\"),\n\t\t\t\"slug\" : jQuery(this).data(\"subsectionSlug\"),\n\t\t})\n\t})\n\n\t// Create tabs for sections\n\tsections.forEach(\n\t\tfunction (section) {\n\t\t\tlet badge = section[\"badgeCount\"] > 0 ? \"<span class=\\\"pmw-tab-badge\\\">\" + section[\"badgeCount\"] + \"</span>\" : \"\"\n\t\t\tjQuery(\".nav-tab-wrapper\").append(\"<a href=\\\"#\\\" class=\\\"nav-tab\\\" data-section-slug=\\\"\" + section[\"slug\"] + \"\\\">\" + section[\"title\"] + badge + \"</a>\")\n\t\t})\n\n\t// Create tabs for each subsections\n\tjQuery(\".nav-tab-wrapper\").after(wpmCreateSubtabUlHtml(subsections))\n\n\t// Create on-click events on section tabs that toggle the views\n\tjQuery(\".nav-tab-wrapper a\").on(\"click\", function (e) {\n\n\t\te.preventDefault()\n\n\t\t// show clicked tab as active\n\t\tjQuery(this).addClass(\"nav-tab-active\").siblings().removeClass(\"nav-tab-active\")\n\n\t\t// toggle the sections visible / invisible based on clicked tab\n\n\t\tlet sectionSlug = jQuery(this).data(\"section-slug\")\n\t\twpmToggleSections(sectionSlug, sections)\n\n\t\t// if subsection exists, click on first subsection\n\t\tif (sectionSlug in subsections) {\n\t\t\tjQuery(\"ul[data-section-slug=\" + sectionSlug + \"]\").children(\":first\").trigger(\"click\")\n\t\t}\n\t})\n\n\t// Create on-click events on subsection tabs that toggle the views\n\tjQuery(\".pmw-subnav-li\").on(\"click\", function (e) {\n\n\t\te.preventDefault()\n\t\te.stopPropagation()\n\n\t\t// jQuery(this).hide();\n\t\tjQuery(this)\n\t\t\t.addClass(\"pmw-subnav-li-active\").removeClass(\"pmw-subnav-li-inactive\")\n\t\t\t.siblings()\n\t\t\t.addClass(\"pmw-subnav-li-inactive\").removeClass(\"pmw-subnav-li-active\")\n\n\t\twpmToggleSubsection(jQuery(this).parent().data(\"section-slug\"), jQuery(this).data(\"subsection-slug\"))\n\t})\n\n\t/**\n\t * If someone accesses a plugin tab by deep link, open the right tab\n\t * or fallback to default (first tab)\n\t *\n\t * If deeplink is being opened,\n\t * open the according section and subsection\n\t */\n\tif (wpmGetSectionParams()) {\n\n\t\tlet sectionParams = wpmGetSectionParams()\n\n\t\tjQuery(\"a[data-section-slug=\" + sectionParams[\"section\"] + \"]\").trigger(\"click\")\n\n\t\tif (sectionParams[\"subsection\"] !== false) {\n\t\t\tjQuery(\"ul[data-section-slug=\" + sectionParams[\"section\"] + \"]\").children(\"[data-subsection-slug=\" + sectionParams[\"subsection\"] + \"]\").trigger(\"click\")\n\t\t}\n\t} else {\n\t\tjQuery(\"a[data-section-slug=\" + sections[0][\"slug\"] + \"]\").trigger(\"click\")\n\t}\n})\n\n// Creates the html with all subsection elements\nwpmCreateSubtabUlHtml = (subsections) => {\n\n\tlet subsectionsKeys = Object.keys(subsections)\n\n\tlet html = \"\"\n\n\tsubsectionsKeys.forEach(function (subsectionKey) {\n\t\thtml += \"<ul class=\\\"pmw-subnav-tabs\\\" data-section-slug=\\\"\" + subsectionKey + \"\\\">\"\n\n\t\tlet subtabs = subsections[subsectionKey]\n\n\t\tsubtabs.forEach(function (subtab) {\n\t\t\thtml += \"<li class=\\\"pmw-subnav-li pmw-subnav-li-inactive\\\" style=\\\"cursor: pointer;\\\" data-subsection-slug=\\\"\" + subtab[\"slug\"] + \"\\\">\" + subtab[\"title\"] + \"</li>\"\n\t\t})\n\n\t\thtml += \"</ul>\"\n\t})\n\n\treturn html\n}\n\n/**\n * If section (and subsection) URL parameters are set,\n * return them, otherwise return false\n */\nwpmGetSectionParams = () => {\n\n\tconst queryString = window.location.search\n\tconst urlParams   = new URLSearchParams(queryString)\n\n\tif (urlParams.get(\"section\")) {\n\t\treturn {\n\t\t\t\"section\"   : urlParams.get(\"section\"),\n\t\t\t\"subsection\": urlParams.get(\"subsection\"),\n\t\t}\n\t} else {\n\t\treturn false\n\t}\n}\n\n// Toggles the sections\nwpmToggleSections = (sectionSlug, sections) => {\n\n\tjQuery(\"#wpm_settings_form > h2\").nextUntil(\".submit\").andSelf().hide()\n\tjQuery(\".pmw-subnav-tabs\").hide()\n\tjQuery(\".pmw-subnav-tabs[data-section-slug=\" + sectionSlug + \"]\").show()\n\n\tlet sectionPos = sections.findIndex((arrayElement) => arrayElement[\"slug\"] === sectionSlug)\n\n\tjQuery(\"div[data-section-slug=\" + sectionSlug + \"]\").closest(\"table\").prevAll(\"h2:first\").next().nextUntil(\"h2, .submit\").andSelf().show()\n\n\t// set the URL with the active tab parameter\n\twpmSetUrl(sections[sectionPos][\"slug\"])\n}\n\nconst wpmToggleSubsection = (sectionSlug, subsectionSlug) => {\n\n\tjQuery(\"#wpm_settings_form > h2\").nextUntil(\".submit\").andSelf().hide()\n\tjQuery(\"[data-section-slug=\" + sectionSlug + \"][data-subsection-slug=\" + subsectionSlug + \"]\").closest(\"tr\").siblings().andSelf().hide()\n\n\tjQuery(\"[data-section-slug=\" + sectionSlug + \"][data-subsection-slug=\" + subsectionSlug + \"]\").closest(\"table\").show()\n\tjQuery(\"[data-section-slug=\" + sectionSlug + \"][data-subsection-slug=\" + subsectionSlug + \"]\").closest(\"tr\").nextUntil(jQuery(\"[data-section-slug=\" + sectionSlug + \"][data-subsection-slug]\").closest(\"tr\")).show()\n\n\t// Set the URL with the active tab parameter\n\twpmSetUrl(sectionSlug, subsectionSlug)\n}\n\n// Sets the new URL parameters\nwpmSetUrl = (sectionSlug, subsectionSlug = \"\") => {\n\n\tconst queryString = window.location.search\n\tconst urlParams   = new URLSearchParams(queryString)\n\n\turlParams.delete(\"section\")\n\turlParams.delete(\"subsection\")\n\n\tlet newParams = \"section=\" + sectionSlug\n\tnewParams += subsectionSlug ? \"&subsection=\" + subsectionSlug : \"\"\n\n\thistory.pushState(\"\", \"wpm\" + sectionSlug, document.location.pathname + \"?page=wpm&\" + newParams)\n\n\t// Make WP remember which was the selected tab on a save and return to the same tab after saving\n\tjQuery(\"input[name =\\\"_wp_http_referer\\\"]\").val(wpmGetAdminPath() + \"?page=wpm&\" + newParams + \"&settings-updated=true\")\n}\n\nwpmGetAdminPath = () => {\n\tlet url = new URL(jQuery(\"#wp-admin-canonical\").attr(\"href\"))\n\treturn url.pathname\n}\n\nwpmGetPageId = () => {\n\n\tconst queryString = window.location.search\n\tconst urlParams   = new URLSearchParams(queryString)\n\n\treturn urlParams.get(\"page\")\n}\n\n// On click of an element that contains a data-section-slug with any value show an alert box with the text hello\njQuery(document).on(\"click\", \"[data-section-slug]\", function () {\n\n\tconst infoTabs = [\n\t\t\"opportunities\",\n\t\t\"diagnostics\",\n\t\t\"support\",\n\t]\n\n\t// If the data-section-slug value is one of infoTabs, hide the save button, otherwise show it\n\tif (infoTabs.includes(jQuery(this).data(\"section-slug\"))) {\n\t\t// Hide the element with class submit\n\t\tjQuery(\".submit\").hide()\n\t} else {\n\t\t// Show the element with class submit\n\t\tjQuery(\".submit\").show()\n\t}\n})\n\n\n// if a link with the class advanced-section-link is clicked,\n// get the data-AS-section and the data-AS-subsection values of the clicked element\n// and trigger a click on the element with the data-ssection-slug value and a click on the element with the data-subsection-slug value\njQuery(document).on(\"click\", \".advanced-section-link\", (e) => {\n\n\te.preventDefault()\n\n\tlet sectionSlug    = jQuery(e.currentTarget).data(\"as-section\")\n\tlet subsectionSlug = jQuery(e.currentTarget).data(\"as-subsection\")\n\n\tjQuery(`a[data-section-slug=${sectionSlug}]`).trigger(\"click\")\n\n\tjQuery(`ul[data-section-slug=${sectionSlug}]`).children(`[data-subsection-slug=${subsectionSlug}]`).trigger(\"click\")\n})\n","jQuery(function () {\n\n\t/**\n\t * Copy debug info to clipboard when the button is clicked.\n\t */\n\tjQuery(\"#debug-info-button\").on(\"click\", () => {\n\t\t// Select text in textarea\n\t\tconst textarea = jQuery(\"#debug-info-textarea\")[0];\n\t\ttextarea.select();\n\t\ttextarea.setSelectionRange(0, 99999); // For mobile devices\n\n\t\t// Copy selected text to clipboard\n\t\twpm.copyTextToClipboard(jQuery(\"#debug-info-textarea\").val());\n\n\t\t// Show success message and hide after 3 seconds\n\t\tconst successElement = jQuery(\"#debug-info-success\");\n\t\tsuccessElement.fadeIn(200);\n\t\tsetTimeout(() => successElement.fadeOut(200), 3000);\n\t});\n\n\tjQuery(\"#pmw-pro-version-demo\").on(\"click\", function () {\n\t\tjQuery(\"#submit\").trigger(\"click\");\n\t});\n\n\tif (document.getElementById(\"json-settings-file-input\")) {\n\t\tdocument.getElementById(\"json-settings-file-input\")\n\t\t\t.addEventListener(\"change\", wpm.readSettingsFile, false);\n\t}\n\n\t// if element ga4-data-api-credentials-upload-button exists, then we are on the GA4 settings page\n\tif (document.getElementById(\"ga4-data-api-credentials-upload-button\")) {\n\n\t\tdocument.getElementById(\"ga4-data-api-credentials-upload-button\")\n\t\t\t.addEventListener(\"change\", wpm.readGa4DataApiCredentials, false);\n\t}\n\n\t// if element ga4-data-api-credentials-upload-button exists, then we are on the GA4 settings page\n\tif (document.getElementById(\"ga4-data-api-credentials-delete-button\")) {\n\n\t\tdocument.getElementById(\"ga4-data-api-credentials-delete-button\")\n\t\t\t.addEventListener(\"click\", () => {\n\t\t\t\twpm.saveGa4DataApiCredentialsToDb({});\n\t\t\t}, false);\n\t}\n\n\t/**\n\t * Handle log files download via REST API\n\t */\n\tjQuery(\"#wgact_download_logs_zip\").on(\"click\", function(e) {\n\t\te.preventDefault();\n\t\t\n\t\tif (jQuery(this).prop(\"disabled\")) {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tconst source = jQuery(this).data(\"source\");\n\t\tconst button = jQuery(this);\n\t\tconst originalText = button.text();\n\t\t\n\t\t// Disable button and change text\n\t\tbutton.prop(\"disabled\", true).text(\"Downloading...\");\n\t\t\n\t\t// Use fetch with proper authentication\n\t\tfetch(pmwAdminApi.root + \"pmw/v1/logs/download\", {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\t\"X-WP-Nonce\": pmwAdminApi.nonce\n\t\t\t},\n\t\t\tbody: new URLSearchParams({\n\t\t\t\tsource: source\n\t\t\t}),\n\t\t\tcredentials: 'same-origin'\n\t\t})\n\t\t.then(response => {\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow new Error(`HTTP error! status: ${response.status}`);\n\t\t\t}\n\t\t\treturn response.blob();\n\t\t})\n\t\t.then(blob => {\n\t\t\t// Create download link\n\t\t\tconst url = window.URL.createObjectURL(blob);\n\t\t\tconst a = document.createElement(\"a\");\n\t\t\ta.href = url;\n\t\t\ta.download = \"pmw-logs-\" + new Date().toISOString().slice(0,19).replace(/:/g, \"-\") + \".zip\";\n\t\t\tdocument.body.appendChild(a);\n\t\t\ta.click();\n\t\t\twindow.URL.revokeObjectURL(url);\n\t\t\tdocument.body.removeChild(a);\n\t\t\t\n\t\t\t// Re-enable the button\n\t\t\tbutton.prop(\"disabled\", false).text(originalText);\n\t\t})\n\t\t.catch(error => {\n\t\t\tconsole.error(\"Download error:\", error);\n\t\t\tbutton.prop(\"disabled\", false).text(originalText);\n\t\t\talert(\"Error downloading log files. Please try again.\");\n\t\t});\n\t});\n});\n\n// jQuery(function () {\n//\n// \timport(\"../../../node_modules/@floating-ui/dom/dist/floating-ui.dom.mjs\")\n// \t\t.then(({\n// \t\t\t\t   computePosition,\n// \t\t\t\t   flip,\n// \t\t\t\t   shift,\n// \t\t\t\t   offset,\n// \t\t\tarrow,\n// \t\t\t   }) => {\n// \t\t\tconsole.log(\"computePosition: \", computePosition)\n//\n// \t\t\tconst button = document.querySelector('#button');\n// \t\t\tconst tooltip = document.querySelector('#tooltip');\n// \t\t\tconst arrowElement = document.querySelector('#arrow');\n//\n// \t\t\tcomputePosition(button, tooltip, {\n// \t\t\t\tplacement: 'top',\n// \t\t\t\tmiddleware: [\n// \t\t\t\t\toffset(6),\n// \t\t\t\t\tflip(),\n// \t\t\t\t\tshift({padding: 5}),\n// \t\t\t\t\tarrow({element: arrowElement}),\n// \t\t\t\t],\n// \t\t\t}).then(({x, y}) => {\n// \t\t\t\tObject.assign(tooltip.style, {\n// \t\t\t\t\tleft: `${x}px`,\n// \t\t\t\t\ttop: `${y}px`,\n// \t\t\t\t});\n// \t\t\t});\n//\n// \t\t})\n// \t\t.catch(err => {\n// \t\t\tconsole.error(err)\n// \t\t})\n//\n// });\n\n\n(function (wpm, $, undefined) {\n\n\twpm.saveSettingsToDisk = () => {\n\t\tlet text = document.getElementById(\"export-settings-json\").value;\n\n\t\t// Extract timestamp from the settings JSON\n\t\tlet timestamp = \"unknown\";\n\t\ttry {\n\t\t\tlet settings = JSON.parse(text);\n\t\t\tif (settings.timestamp) {\n\t\t\t\ttimestamp = settings.timestamp;\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.warn(\"Could not extract timestamp from settings:\", error);\n\t\t}\n\n\t\ttext                 = text.replace(/\\n/g, \"\\r\\n\"); // To retain the Line breaks.\n\t\tlet blob             = new Blob([text], {type: \"text/plain\"});\n\t\tlet anchor           = document.createElement(\"a\");\n\t\tanchor.download      = \"pixel-manager-settings_\" + timestamp + \"_\" + wpm.getDateTimeFromTimestamp(timestamp) + \".json\";\n\t\tanchor.href          = window.URL.createObjectURL(blob);\n\t\tanchor.target        = \"_blank\";\n\t\tanchor.style.display = \"none\"; // just to be safe!\n\t\tdocument.body.appendChild(anchor);\n\t\tanchor.click();\n\t\tdocument.body.removeChild(anchor);\n\t};\n\n\t// Get date and time from timestamp in year.month.day_hour-minute-second format. All components are zero padded.\n\t// Uses WordPress site timezone to match what's displayed on admin pages.\n\twpm.getDateTimeFromTimestamp = (timestamp) => {\n\t\t// If timestamp is \"unknown\" or invalid, fall back to current date/time\n\t\tif (timestamp === \"unknown\" || !timestamp || isNaN(timestamp)) {\n\t\t\treturn wpm.getCurrentDateForFileName();\n\t\t}\n\n\t\t// Convert Unix timestamp (seconds) to milliseconds for JavaScript Date\n\t\tlet date = new Date(timestamp * 1000);\n\n\t\t// Apply WordPress timezone offset if available\n\t\tif (pmwAdminApi && pmwAdminApi.timezone && typeof pmwAdminApi.timezone.offset === \"number\") {\n\t\t\t// Create new date in WordPress timezone by adding the offset\n\t\t\tlet wpTimezoneOffsetMs = pmwAdminApi.timezone.offset * 60 * 60 * 1000; // Convert hours to milliseconds\n\t\t\tdate                   = new Date(date.getTime() + wpTimezoneOffsetMs);\n\n\t\t\t// Get WordPress timezone date/time components using UTC methods\n\t\t\t// (since we've already applied the offset to the date object)\n\t\t\tlet year    = date.getUTCFullYear();\n\t\t\tlet month   = (\"0\" + (date.getUTCMonth() + 1)).slice(-2);\n\t\t\tlet day     = (\"0\" + date.getUTCDate()).slice(-2);\n\t\t\tlet hours   = (\"0\" + date.getUTCHours()).slice(-2);\n\t\t\tlet minutes = (\"0\" + date.getUTCMinutes()).slice(-2);\n\t\t\tlet seconds = (\"0\" + date.getUTCSeconds()).slice(-2);\n\n\t\t\treturn year + \".\" + month + \".\" + day + \"_\" + hours + \"-\" + minutes + \"-\" + seconds;\n\t\t} else {\n\t\t\t// Fallback to browser local timezone if WordPress timezone data is not available\n\t\t\tlet year    = date.getFullYear();\n\t\t\tlet month   = (\"0\" + (date.getMonth() + 1)).slice(-2);\n\t\t\tlet day     = (\"0\" + date.getDate()).slice(-2);\n\t\t\tlet hours   = (\"0\" + date.getHours()).slice(-2);\n\t\t\tlet minutes = (\"0\" + date.getMinutes()).slice(-2);\n\t\t\tlet seconds = (\"0\" + date.getSeconds()).slice(-2);\n\t\t\treturn year + \".\" + month + \".\" + day + \"_\" + hours + \"-\" + minutes + \"-\" + seconds;\n\t\t}\n\t};\n\n\t// Get current date and time in year.month.day_hour-minute-second format. All components are zero padded.\n\t// Uses WordPress site timezone to match what's displayed on admin pages.\n\twpm.getCurrentDateForFileName = () => {\n\t\tlet date = new Date();\n\n\t\t// Apply WordPress timezone offset if available\n\t\tif (pmwAdminApi && pmwAdminApi.timezone && typeof pmwAdminApi.timezone.offset === \"number\") {\n\t\t\t// Apply WordPress timezone offset\n\t\t\tlet wpTimezoneOffsetMs = pmwAdminApi.timezone.offset * 60 * 60 * 1000; // Convert hours to milliseconds\n\t\t\tdate                   = new Date(date.getTime() + wpTimezoneOffsetMs);\n\n\t\t\t// Get WordPress timezone date/time components using UTC methods\n\t\t\t// (since we've already applied the offset to the date object)\n\t\t\tlet year    = date.getUTCFullYear();\n\t\t\tlet month   = (\"0\" + (date.getUTCMonth() + 1)).slice(-2);\n\t\t\tlet day     = (\"0\" + date.getUTCDate()).slice(-2);\n\t\t\tlet hours   = (\"0\" + date.getUTCHours()).slice(-2);\n\t\t\tlet minutes = (\"0\" + date.getUTCMinutes()).slice(-2);\n\t\t\tlet seconds = (\"0\" + date.getUTCSeconds()).slice(-2);\n\n\t\t\treturn year + \".\" + month + \".\" + day + \"_\" + hours + \"-\" + minutes + \"-\" + seconds;\n\t\t} else {\n\t\t\t// Fallback to browser local timezone if WordPress timezone data is not available\n\t\t\tlet year    = date.getFullYear();\n\t\t\tlet month   = (\"0\" + (date.getMonth() + 1)).slice(-2);\n\t\t\tlet day     = (\"0\" + date.getDate()).slice(-2);\n\t\t\tlet hours   = (\"0\" + date.getHours()).slice(-2);\n\t\t\tlet minutes = (\"0\" + date.getMinutes()).slice(-2);\n\t\t\tlet seconds = (\"0\" + date.getSeconds()).slice(-2);\n\t\t\treturn year + \".\" + month + \".\" + day + \"_\" + hours + \"-\" + minutes + \"-\" + seconds;\n\t\t}\n\n\t\t// return date.toLocaleDateString(\n\t\t// \t\"en-US\", {\n\t\t// \t\tyear : \"numeric\",\n\t\t// \t\tmonth: \"2-digit\",\n\t\t// \t\tday  : \"2-digit\",\n\t\t// \t},\n\t\t// )\n\t};\n\n\twpm.readSettingsFile = e => {\n\n\t\tlet file = e.target.files[0];\n\t\tif (!file) return;\n\t\tlet reader    = new FileReader();\n\t\treader.onload = function (e) {\n\n\t\t\t// Check if the file is a valid JSON file\n\t\t\t// If it is not a valid JSON file, display an error message\n\t\t\ttry {\n\t\t\t\tJSON.parse(e.target.result);\n\t\t\t} catch (error) {\n\t\t\t\tdocument.getElementById(\"settings-upload-status-error\").style.display     = \"block\";\n\t\t\t\tdocument.getElementById(\"settings-upload-status-error-message\").innerHTML = \"Invalid JSON file.\";\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet contents = JSON.parse(e.target.result);\n\n\t\t\t// document.getElementById(\"import-settings-json\").textContent = JSON.stringify(contents)\n\n\t\t\twpm.saveImportedSettingsToDb(contents);\n\t\t};\n\t\treader.readAsText(file);\n\t};\n\n\twpm.saveImportedSettingsToDb = settings => {\n\n\t\tfetch(pmwAdminApi.root + \"pmw/v1/settings/\", {\n\t\t\tmethod     : \"POST\",\n\t\t\tcredentials: \"same-origin\",\n\t\t\theaders    : {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\"X-WP-Nonce\"  : pmwAdminApi.nonce,\n\t\t\t},\n\t\t\tbody       : JSON.stringify(settings),\n\t\t})\n\t\t\t.then(response => response.json())\n\t\t\t.then(async message => {\n\t\t\t\tif (message.success) {\n\t\t\t\t\tconsole.log(message);\n\t\t\t\t\t// reload window\n\t\t\t\t\tdocument.getElementById(\"settings-upload-status-success\").style.display = \"block\";\n\t\t\t\t\t// wait 5 seconds\n\t\t\t\t\tawait new Promise(resolve => setTimeout(resolve, 1000));\n\t\t\t\t\twindow.location.reload();\n\t\t\t\t} else {\n\t\t\t\t\tconsole.log(message);\n\t\t\t\t\tdocument.getElementById(\"settings-upload-status-error\").style.display = \"block\";\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch(error => {\n\t\t\t\tconsole.error(error);\n\t\t\t\tdocument.getElementById(\"settings-upload-status-error\").style.display = \"block\";\n\t\t\t});\n\t};\n\n\twpm.restoreBackup = (timestamp) => {\n\n\t\tconsole.log(\"restoreBackup() - timestamp: \", timestamp);\n\n\t\tfetch(pmwAdminApi.root + \"pmw/v1/options-backup/\" + timestamp + \"/restore\", {\n\t\t\tmethod     : \"POST\",\n\t\t\tcredentials: \"same-origin\",\n\t\t\theaders    : {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\"X-WP-Nonce\"  : pmwAdminApi.nonce,\n\t\t\t},\n\t\t})\n\t\t\t.then(response => response.json())\n\t\t\t.then(async message => {\n\n\t\t\t\tif (message?.data?.message) {\n\t\t\t\t\tconsole.log(\"restoreBackup() - message: \", message.data.message);\n\t\t\t\t}\n\n\t\t\t\tif (message.success) {\n\t\t\t\t\twindow.location.reload();\n\t\t\t\t} else {\n\t\t\t\t\talert(message.data.message);\n\t\t\t\t}\n\n\t\t\t})\n\t\t\t.catch(error => {\n\t\t\t\tconsole.error(error);\n\t\t\t\talert(error.message);\n\t\t\t});\n\t};\n\n\twpm.readGa4DataApiCredentials = e => {\n\n\t\tlet file = e.target.files[0];\n\t\tif (!file) return;\n\t\tlet reader    = new FileReader();\n\t\treader.onload = function (e) {\n\n\t\t\t// Check if the file is a valid JSON file\n\t\t\t// If it is not a valid JSON file, display an error message\n\t\t\ttry {\n\t\t\t\tJSON.parse(e.target.result);\n\t\t\t} catch (error) {\n\t\t\t\tdocument.getElementById(\"ga4-api-credentials-upload-status-error\").style.display     = \"block\";\n\t\t\t\tdocument.getElementById(\"ga4-api-credentials-upload-status-error-message\").innerHTML = \"Invalid JSON file.\";\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet contents = JSON.parse(e.target.result);\n\n\t\t\t// document.getElementById(\"import-settings-json\").textContent = JSON.stringify(contents)\n\n\t\t\twpm.saveGa4DataApiCredentialsToDb(contents);\n\t\t};\n\t\treader.readAsText(file);\n\t};\n\n\twpm.deleteGa4DataApiCredentials = e => {\n\t\twpm.saveGa4DataApiCredentialsToDb({});\n\t};\n\n\twpm.saveGa4DataApiCredentialsToDb = credentials => {\n\n\t\tfetch(pmwAdminApi.root + \"pmw/v1/ga4/data-api/credentials\", {\n\t\t\tmethod     : \"POST\",\n\t\t\tcredentials: \"same-origin\",\n\t\t\theaders    : {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\"X-WP-Nonce\"  : pmwAdminApi.nonce,\n\t\t\t},\n\t\t\tbody       : JSON.stringify(credentials),\n\t\t})\n\t\t\t.then(response => response.json())\n\t\t\t.then(async responseJson => {\n\t\t\t\tif (responseJson.success) {\n\t\t\t\t\tconsole.log(responseJson);\n\t\t\t\t\t// reload window\n\t\t\t\t\tdocument.getElementById(\"ga4-api-credentials-upload-status-success\").style.display = \"block\";\n\t\t\t\t\t// wait 5 seconds\n\t\t\t\t\t// await new Promise(resolve => setTimeout(resolve, 5000))\n\t\t\t\t\twindow.location.reload();\n\t\t\t\t} else {\n\t\t\t\t\tconsole.log(responseJson);\n\t\t\t\t\tdocument.getElementById(\"ga4-api-credentials-upload-status-error\").style.display     = \"block\";\n\t\t\t\t\t// and add the error message\n\t\t\t\t\tdocument.getElementById(\"ga4-api-credentials-upload-status-error-message\").innerHTML = \"Error message: \" + responseJson.data.message;\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch(error => {\n\t\t\t\tconsole.error(error);\n\t\t\t\tdocument.getElementById(\"ga4-api-credentials-upload-status-error\").style.display = \"block\";\n\t\t\t});\n\t};\n\n\twpm.getAiBotUrl = () => {\n\t\tif (pmw_cody?.url) {\n\t\t\treturn pmw_cody.url;\n\t\t}\n\t};\n\n\t/**\n\t * Opens the chatbot in a side panel (like n8n)\n\t * The panel slides in from the right side of the screen\n\t */\n\twpm.loadAiChatWindow = () => {\n\t\tconst panel = document.getElementById(\"pmw-chatbot-panel\");\n\t\tconst iframe = document.getElementById(\"pmw-chatbot-iframe\");\n\n\t\tif (!panel || !iframe) {\n\t\t\tconsole.error(\"Chatbot panel elements not found\");\n\t\t\treturn;\n\t\t}\n\n\t\t// Set the iframe source\n\t\tiframe.src = wpm.getAiBotUrl();\n\n\t\t// Add body class to push content left\n\t\tdocument.body.classList.add(\"pmw-chatbot-open\");\n\n\t\t// Open the panel\n\t\tpanel.classList.add(\"pmw-chatbot-panel-open\");\n\t};\n\n\t/**\n\t * Closes the chatbot side panel\n\t */\n\twpm.closeChatbot = () => {\n\t\tconst panel = document.getElementById(\"pmw-chatbot-panel\");\n\t\tif (panel) {\n\t\t\tpanel.classList.remove(\"pmw-chatbot-panel-open\");\n\t\t\t// Remove body class to restore content position\n\t\t\tdocument.body.classList.remove(\"pmw-chatbot-open\");\n\t\t}\n\t};\n\n\t/**\n\t * Check if the Cody AI chatbot is available.\n\t *\n\t * @return {boolean}\n\t */\n\twpm.codyAvailable = () => {\n\t\tif (typeof window.pmw_cody !== \"undefined\" && window.pmw_cody?.available) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t};\n\n\t// Schedule a recalculation of the LTV by sending a POST REST request to the server\n\twpm.ltvRecalculation = event => {\n\n\t\tconst displayStatusMessage = (message) => {\n\t\t\tlet elements = document.getElementsByClassName(\"ltv-message\");\n\t\t\tfor (let i = 0; i < elements.length; i++) {\n\t\t\t\telements[i].style.display = \"none\";\n\t\t\t}\n\t\t\tdocument.getElementById(\"ltv-message-error\").style.display  = \"block\";\n\t\t\tdocument.getElementById(\"ltv-message-error-text\").innerHTML = message;\n\t\t};\n\n\t\tconst displayRunImmediatelyButton = () => {\n\t\t\tlet elements = document.getElementsByClassName(\"ltv-button-text\");\n\t\t\tfor (let i = 0; i < elements.length; i++) {\n\t\t\t\telements[i].style.display = \"none\";\n\t\t\t}\n\t\t\tdocument.getElementById(\"ltv-instant-recalculation-button-text\").style.display = \"block\";\n\t\t};\n\n\t\tconst removeAllMessages = () => {\n\t\t\tlet elements = document.getElementsByClassName(\"ltv-message\");\n\t\t\tfor (let i = 0; i < elements.length; i++) {\n\t\t\t\telements[i].style.display = \"none\";\n\t\t\t}\n\n\t\t\tdocument.getElementById(\"ltv-message-error\").style.display = \"none\";\n\t\t};\n\n\t\t// console log the data-action from the nested span element of the clicked element\n\t\t// console.log(\"event.target.dataset.action\", event.target.dataset.action)\n\n\t\tfetch(pmwAdminApi.root + \"pmw/v1/ltv/\", {\n\t\t\tmethod     : \"POST\",\n\t\t\tcredentials: \"same-origin\",\n\t\t\theaders    : {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\"X-WP-Nonce\"  : pmwAdminApi.nonce,\n\t\t\t},\n\t\t\tbody       : JSON.stringify({\n\t\t\t\t\"action\": event.target.dataset.action,\n\t\t\t}),\n\t\t})\n\t\t\t.then(response => response.json())\n\t\t\t.then(message => {\n\t\t\t\tif (message.success) {\n\t\t\t\t\tconsole.log(message);\n\t\t\t\t\t// reload window\n\n\t\t\t\t\tif (message.data.status.is_scheduled) {\n\t\t\t\t\t\tremoveAllMessages();\n\t\t\t\t\t\tdisplayRunImmediatelyButton();\n\t\t\t\t\t\tdocument.getElementById(\"ltv-schedule-recalculation-confirmation-message\").style.display = \"block\";\n\t\t\t\t\t}\n\n\t\t\t\t\tif (message.data.status.is_running) {\n\t\t\t\t\t\t// Get the button element with the id \"wgact_ltv_recalculation\" and disable it\n\t\t\t\t\t\tdocument.getElementById(\"wgact_ltv_recalculation\").disabled = true;\n\t\t\t\t\t\tremoveAllMessages();\n\t\t\t\t\t\tdocument.getElementById(\"ltv-running-recalculation-confirmation-message\").style.display = \"block\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// if is neither message.data.status.is_running nor message.data.status.is_scheduled\n\t\t\t\t\t// then display the error message\n\t\t\t\t\tif (!message.data.status.is_running && !message.data.status.is_scheduled) {\n\t\t\t\t\t\tdisplayStatusMessage(message.data.message);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tconsole.error(message);\n\t\t\t\t\tdisplayStatusMessage(message.data.message);\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch(error => {\n\t\t\t\tconsole.error(error);\n\t\t\t\tdisplayStatusMessage(error);\n\t\t\t});\n\t};\n\n\twpm.copyTextToClipboard = (text) => {\n\t\tnavigator.clipboard.writeText(text)\n\t\t\t.catch(err => {\n\t\t\t\tconsole.error(\"Failed to copy: \", err);\n\t\t\t});\n\t};\n\n}(window.wpm = window.wpm || {}, jQuery));\n\n/**\n * This script listens for the DOMContentLoaded event. Once the DOM is fully loaded,\n * it checks if the chatbot (wpm.codyAvailable()) is available.\n * If the chatbot is available, it displays the chat widget button.\n * If the chatbot is not available, it logs a message to the console indicating that the chatbot is unavailable.\n *\n * @listens document#DOMContentLoaded\n */\ndocument.addEventListener(\"DOMContentLoaded\", () => {\n\n\tif (wpm.codyAvailable()) {\n\t\tconst chatbotWidget = document.getElementById(\"pmw-chatbot-widget\");\n\t\tif (chatbotWidget) {\n\t\t\tchatbotWidget.style.display = \"block\";\n\t\t}\n\n\t\t// Show the chatbot line in the support section\n\t\tconst chatbotListItem = document.getElementById(\"pmw-chat-li\");\n\t\tif (chatbotListItem) {\n\t\t\tchatbotListItem.style.display = \"list-item\";\n\t\t}\n\n\t\t// Set up event listeners for the chatbot widget\n\t\tconst chatbotToggle = document.getElementById(\"pmw-chatbot-toggle\");\n\t\tconst chatbotClose = document.getElementById(\"pmw-chatbot-close\");\n\n\t\tif (chatbotToggle) {\n\t\t\tchatbotToggle.addEventListener(\"click\", (e) => {\n\t\t\t\te.preventDefault();\n\t\t\t\twpm.loadAiChatWindow();\n\t\t\t});\n\t\t}\n\n\t\tif (chatbotClose) {\n\t\t\tchatbotClose.addEventListener(\"click\", (e) => {\n\t\t\t\te.preventDefault();\n\t\t\t\twpm.closeChatbot();\n\t\t\t});\n\t\t}\n\n\t\t// Close chatbot on ESC key\n\t\tdocument.addEventListener(\"keydown\", (event) => {\n\t\t\tif (event.key === \"Escape\") {\n\t\t\t\twpm.closeChatbot();\n\t\t\t}\n\t\t});\n\t} else {\n\t\tconsole.log(\"DOMContentLoaded - chatbot is not available\");\n\t}\n\n}, true);\n\n// Wait until the DOM is loaded, then console log\n// the message \"DOMContentLoaded - chatbot is not available\"\n// use jquery\njQuery(() => {\n\tif (document.querySelector(\"#wgact_ltv_recalculation\")) {\n\t\tdocument.querySelector(\"#wgact_ltv_recalculation\").addEventListener(\"click\", event => {\n\t\t\tevent.preventDefault();\n\t\t\twpm.ltvRecalculation(event);\n\t\t});\n\t}\n\n\tif (document.querySelector(\"#pmw_stop_ltv_calculation\")) {\n\t\tdocument.querySelector(\"#pmw_stop_ltv_calculation\").addEventListener(\"click\", event => {\n\t\t\tevent.preventDefault();\n\t\t\twpm.ltvRecalculation(event);\n\t\t});\n\t}\n\n\t// Add event listeners for backup restore buttons\n\tjQuery(() => {\n\t\tjQuery(document).on(\"click\", \".pmw-restore-backup-button\", function (event) {\n\t\t\tevent.preventDefault();\n\t\t\tconst timestamp = jQuery(this).data(\"timestamp\");\n\t\t\tif (timestamp) {\n\t\t\t\twpm.restoreBackup(timestamp);\n\t\t\t}\n\t\t});\n\t});\n});\n\n/**\n * add an event listener to the button with the id \"wgact_copy_log_file_links\"\n * when the button is clicked, copy the log file links to the clipboard\n * the data-links attribute of the button contains a json string with the links\n */\njQuery(() => {\n\n\tif (!document.querySelector(\"#wgact_copy_log_file_links\")) {\n\t\treturn;\n\t}\n\n\tdocument.querySelector(\"#wgact_copy_log_file_links\").addEventListener(\"click\", event => {\n\t\tevent.preventDefault();\n\n\t\tconst jsonOfLinks = JSON.parse(event.target.dataset.links);\n\n\t\tlet strOfLinks = \"\";\n\n\t\tfor (let i = 0, len = jsonOfLinks.length; i < len; i++) {\n\t\t\tstrOfLinks += jsonOfLinks[i] + \"\\n\";\n\t\t}\n\n\t\twpm.copyTextToClipboard(strOfLinks);\n\n\t\t// make the button text change to \"Copied!\" and keep the same width and text for 3 seconds\n\t\tlet button         = document.getElementById(\"wgact_copy_log_file_links\");\n\t\tbutton.style.width = getComputedStyle(button).width;\n\t\tconst originalText = button.innerHTML;\n\t\tbutton.innerHTML   = event.target.dataset.textCopied;\n\t\tsetTimeout(function () {\n\t\t\tbutton.innerHTML = originalText;\n\t\t}, 3000);\n\t});\n});\n\n// on pressing enter in form inputs, click the submit button\njQuery(() => {\n\tjQuery(document).on(\"keydown\", \"input, textarea, select\", function (event) {\n\t\tif (event.key === \"Enter\" && !event.shiftKey && !event.ctrlKey && !event.altKey) {\n\t\t\t// Only trigger submit if we're in a form and not in a textarea (where Enter should create new lines)\n\t\t\tconst $target = jQuery(event.target);\n\t\t\tif ($target.is(\"input\") && $target.closest(\"form\").length > 0) {\n\t\t\t\tconst form = $target.closest(\"form\")[0];\n\t\t\t\tconst submitButton = jQuery(form).find(\"#submit\");\n\t\t\t\tif (submitButton.length > 0) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tsubmitButton.click();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n});\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","/**\n * Combine all admin scripts\n * (which only run on the wpm pages)\n */\n\n// require(\"./environment-check\")\nrequire(\"./helpers\")\nrequire(\"./script-blocker-warning\")\nrequire(\"./tabs\")\n\n// #if process.env.TIER === 'premium'\n// // require(\"./helpers_premium\")\n// #endif\n\n// console.log('Pixel Manager for WooCommerce admin script')\n"],"names":["wpm_hide_script_blocker_warning","jQuery","hide","wpmGetPageId","sections","subsections","closest","each","push","this","data","forEach","section","badge","append","after","wpmCreateSubtabUlHtml","on","e","preventDefault","addClass","siblings","removeClass","sectionSlug","wpmToggleSections","children","trigger","stopPropagation","wpmToggleSubsection","parent","wpmGetSectionParams","sectionParams","subsectionsKeys","Object","keys","html","subsectionKey","subtab","queryString","window","location","search","urlParams","URLSearchParams","get","nextUntil","andSelf","show","sectionPos","findIndex","arrayElement","prevAll","next","wpmSetUrl","subsectionSlug","delete","newParams","history","pushState","document","pathname","val","wpmGetAdminPath","URL","attr","includes","currentTarget","textarea","select","setSelectionRange","wpm","copyTextToClipboard","successElement","fadeIn","setTimeout","fadeOut","getElementById","addEventListener","readSettingsFile","readGa4DataApiCredentials","saveGa4DataApiCredentialsToDb","prop","source","button","originalText","text","fetch","pmwAdminApi","root","method","headers","nonce","body","credentials","then","response","ok","Error","status","blob","url","createObjectURL","a","createElement","href","download","Date","toISOString","slice","replace","appendChild","click","revokeObjectURL","removeChild","catch","error","console","alert","saveSettingsToDisk","value","timestamp","settings","JSON","parse","warn","Blob","type","anchor","getDateTimeFromTimestamp","target","style","display","isNaN","getCurrentDateForFileName","date","timezone","offset","wpTimezoneOffsetMs","getTime","getUTCFullYear","getUTCMonth","getUTCDate","getUTCHours","getUTCMinutes","getUTCSeconds","getFullYear","getMonth","getDate","getHours","getMinutes","getSeconds","file","files","reader","FileReader","onload","result","innerHTML","contents","saveImportedSettingsToDb","readAsText","stringify","json","async","message","success","log","Promise","resolve","reload","restoreBackup","deleteGa4DataApiCredentials","responseJson","getAiBotUrl","pmw_cody","loadAiChatWindow","panel","iframe","src","classList","add","closeChatbot","remove","codyAvailable","available","ltvRecalculation","event","displayStatusMessage","elements","getElementsByClassName","i","length","removeAllMessages","dataset","action","is_scheduled","displayRunImmediatelyButton","is_running","disabled","navigator","clipboard","writeText","err","chatbotWidget","chatbotListItem","chatbotToggle","chatbotClose","key","querySelector","jsonOfLinks","links","strOfLinks","len","width","getComputedStyle","textCopied","shiftKey","ctrlKey","altKey","$target","is","form","submitButton","find","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","exports","module","__webpack_modules__","require"],"sourceRoot":""}
     1{"version":3,"file":"wpm-admin.p1.min.js","mappings":"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","sources":["webpack://Pixel-Manager-for-WooCommerce/./src/js-src/admin/script-blocker-warning.js","webpack://Pixel-Manager-for-WooCommerce/./src/js-src/admin/tabs.js","webpack://Pixel-Manager-for-WooCommerce/./src/js-src/admin/helpers.js","webpack://Pixel-Manager-for-WooCommerce/webpack/bootstrap","webpack://Pixel-Manager-for-WooCommerce/./src/js-src/admin/main.js"],"sourcesContent":["function wpm_hide_script_blocker_warning() {\n\tjQuery(\"#script-blocker-notice\").hide()\n}\n\n// try to hide as soon as this script is loaded\n// might be too early in some cases, as the HTML is not rendered yet\nwpm_hide_script_blocker_warning()\n\n// if all other earlier attempts to hide did fail\n// run the function after entire DOM has been loaded\njQuery(function () {\n\twpm_hide_script_blocker_warning()\n})\n","jQuery(function () {\n\n\t// Don't run if we are not one of the\n\t// WPM main tabs\n\tif (\"wpm\" !== wpmGetPageId()) return\n\n\tlet sections    = []\n\tlet subsections = {}\n\n\t// Hide unnecessary elements\n\tjQuery(\".section\").closest(\"tr\").hide()\n\n\t// Collect information on sections\n\tjQuery(\".section\").each(function () {\n\t\tsections.push({\n\t\t\t\"slug\"      : jQuery(this).data(\"sectionSlug\"),\n\t\t\t\"title\"     : jQuery(this).data(\"sectionTitle\"),\n\t\t\t\"badgeCount\": jQuery(this).data(\"badgeCount\") || 0,\n\t\t})\n\t})\n\n\t// Collect information on subsections\n\tjQuery(\".subsection\").each(function () {\n\n\t\tsubsections[jQuery(this).data(\"sectionSlug\")] = subsections[jQuery(this).data(\"sectionSlug\")] || []\n\n\t\tsubsections[jQuery(this).data(\"sectionSlug\")].push({\n\t\t\t\"title\": jQuery(this).data(\"subsectionTitle\"),\n\t\t\t\"slug\" : jQuery(this).data(\"subsectionSlug\"),\n\t\t})\n\t})\n\n\t// Create tabs for sections\n\tsections.forEach(\n\t\tfunction (section) {\n\t\t\tlet badge = section[\"badgeCount\"] > 0 ? \"<span class=\\\"pmw-tab-badge\\\">\" + section[\"badgeCount\"] + \"</span>\" : \"\"\n\t\t\tjQuery(\".nav-tab-wrapper\").append(\"<a href=\\\"#\\\" class=\\\"nav-tab\\\" data-section-slug=\\\"\" + section[\"slug\"] + \"\\\">\" + section[\"title\"] + badge + \"</a>\")\n\t\t})\n\n\t// Create tabs for each subsections\n\tjQuery(\".nav-tab-wrapper\").after(wpmCreateSubtabUlHtml(subsections))\n\n\t// Create on-click events on section tabs that toggle the views\n\tjQuery(\".nav-tab-wrapper a\").on(\"click\", function (e) {\n\n\t\te.preventDefault()\n\n\t\t// show clicked tab as active\n\t\tjQuery(this).addClass(\"nav-tab-active\").siblings().removeClass(\"nav-tab-active\")\n\n\t\t// toggle the sections visible / invisible based on clicked tab\n\n\t\tlet sectionSlug = jQuery(this).data(\"section-slug\")\n\t\twpmToggleSections(sectionSlug, sections)\n\n\t\t// if subsection exists, click on first subsection\n\t\tif (sectionSlug in subsections) {\n\t\t\tjQuery(\"ul[data-section-slug=\" + sectionSlug + \"]\").children(\":first\").trigger(\"click\")\n\t\t}\n\t})\n\n\t// Create on-click events on subsection tabs that toggle the views\n\tjQuery(\".pmw-subnav-li\").on(\"click\", function (e) {\n\n\t\te.preventDefault()\n\t\te.stopPropagation()\n\n\t\t// jQuery(this).hide();\n\t\tjQuery(this)\n\t\t\t.addClass(\"pmw-subnav-li-active\").removeClass(\"pmw-subnav-li-inactive\")\n\t\t\t.siblings()\n\t\t\t.addClass(\"pmw-subnav-li-inactive\").removeClass(\"pmw-subnav-li-active\")\n\n\t\twpmToggleSubsection(jQuery(this).parent().data(\"section-slug\"), jQuery(this).data(\"subsection-slug\"))\n\t})\n\n\t/**\n\t * If someone accesses a plugin tab by deep link, open the right tab\n\t * or fallback to default (first tab)\n\t *\n\t * If deeplink is being opened,\n\t * open the according section and subsection\n\t */\n\tif (wpmGetSectionParams()) {\n\n\t\tlet sectionParams = wpmGetSectionParams()\n\n\t\tjQuery(\"a[data-section-slug=\" + sectionParams[\"section\"] + \"]\").trigger(\"click\")\n\n\t\tif (sectionParams[\"subsection\"] !== false) {\n\t\t\tjQuery(\"ul[data-section-slug=\" + sectionParams[\"section\"] + \"]\").children(\"[data-subsection-slug=\" + sectionParams[\"subsection\"] + \"]\").trigger(\"click\")\n\t\t}\n\t} else {\n\t\tjQuery(\"a[data-section-slug=\" + sections[0][\"slug\"] + \"]\").trigger(\"click\")\n\t}\n})\n\n// Creates the html with all subsection elements\nwpmCreateSubtabUlHtml = (subsections) => {\n\n\tlet subsectionsKeys = Object.keys(subsections)\n\n\tlet html = \"\"\n\n\tsubsectionsKeys.forEach(function (subsectionKey) {\n\t\thtml += \"<ul class=\\\"pmw-subnav-tabs\\\" data-section-slug=\\\"\" + subsectionKey + \"\\\">\"\n\n\t\tlet subtabs = subsections[subsectionKey]\n\n\t\tsubtabs.forEach(function (subtab) {\n\t\t\thtml += \"<li class=\\\"pmw-subnav-li pmw-subnav-li-inactive\\\" style=\\\"cursor: pointer;\\\" data-subsection-slug=\\\"\" + subtab[\"slug\"] + \"\\\">\" + subtab[\"title\"] + \"</li>\"\n\t\t})\n\n\t\thtml += \"</ul>\"\n\t})\n\n\treturn html\n}\n\n/**\n * If section (and subsection) URL parameters are set,\n * return them, otherwise return false\n */\nwpmGetSectionParams = () => {\n\n\tconst queryString = window.location.search\n\tconst urlParams   = new URLSearchParams(queryString)\n\n\tif (urlParams.get(\"section\")) {\n\t\treturn {\n\t\t\t\"section\"   : urlParams.get(\"section\"),\n\t\t\t\"subsection\": urlParams.get(\"subsection\"),\n\t\t}\n\t} else {\n\t\treturn false\n\t}\n}\n\n// Toggles the sections\nwpmToggleSections = (sectionSlug, sections) => {\n\n\tjQuery(\"#wpm_settings_form > h2\").nextUntil(\".submit\").andSelf().hide()\n\tjQuery(\".pmw-subnav-tabs\").hide()\n\tjQuery(\".pmw-subnav-tabs[data-section-slug=\" + sectionSlug + \"]\").show()\n\n\tlet sectionPos = sections.findIndex((arrayElement) => arrayElement[\"slug\"] === sectionSlug)\n\n\tjQuery(\"div[data-section-slug=\" + sectionSlug + \"]\").closest(\"table\").prevAll(\"h2:first\").next().nextUntil(\"h2, .submit\").andSelf().show()\n\n\t// set the URL with the active tab parameter\n\twpmSetUrl(sections[sectionPos][\"slug\"])\n}\n\nconst wpmToggleSubsection = (sectionSlug, subsectionSlug) => {\n\n\tjQuery(\"#wpm_settings_form > h2\").nextUntil(\".submit\").andSelf().hide()\n\tjQuery(\"[data-section-slug=\" + sectionSlug + \"][data-subsection-slug=\" + subsectionSlug + \"]\").closest(\"tr\").siblings().andSelf().hide()\n\n\tjQuery(\"[data-section-slug=\" + sectionSlug + \"][data-subsection-slug=\" + subsectionSlug + \"]\").closest(\"table\").show()\n\tjQuery(\"[data-section-slug=\" + sectionSlug + \"][data-subsection-slug=\" + subsectionSlug + \"]\").closest(\"tr\").nextUntil(jQuery(\"[data-section-slug=\" + sectionSlug + \"][data-subsection-slug]\").closest(\"tr\")).show()\n\n\t// Set the URL with the active tab parameter\n\twpmSetUrl(sectionSlug, subsectionSlug)\n}\n\n// Sets the new URL parameters\nwpmSetUrl = (sectionSlug, subsectionSlug = \"\") => {\n\n\tconst queryString = window.location.search\n\tconst urlParams   = new URLSearchParams(queryString)\n\n\turlParams.delete(\"section\")\n\turlParams.delete(\"subsection\")\n\n\tlet newParams = \"section=\" + sectionSlug\n\tnewParams += subsectionSlug ? \"&subsection=\" + subsectionSlug : \"\"\n\n\thistory.pushState(\"\", \"wpm\" + sectionSlug, document.location.pathname + \"?page=wpm&\" + newParams)\n\n\t// Make WP remember which was the selected tab on a save and return to the same tab after saving\n\tjQuery(\"input[name =\\\"_wp_http_referer\\\"]\").val(wpmGetAdminPath() + \"?page=wpm&\" + newParams + \"&settings-updated=true\")\n}\n\nwpmGetAdminPath = () => {\n\tlet url = new URL(jQuery(\"#wp-admin-canonical\").attr(\"href\"))\n\treturn url.pathname\n}\n\nwpmGetPageId = () => {\n\n\tconst queryString = window.location.search\n\tconst urlParams   = new URLSearchParams(queryString)\n\n\treturn urlParams.get(\"page\")\n}\n\n// On click of an element that contains a data-section-slug with any value show an alert box with the text hello\njQuery(document).on(\"click\", \"[data-section-slug]\", function () {\n\n\tconst infoTabs = [\n\t\t\"opportunities\",\n\t\t\"diagnostics\",\n\t\t\"support\",\n\t]\n\n\t// If the data-section-slug value is one of infoTabs, hide the save button, otherwise show it\n\tif (infoTabs.includes(jQuery(this).data(\"section-slug\"))) {\n\t\t// Hide the element with class submit\n\t\tjQuery(\".submit\").hide()\n\t} else {\n\t\t// Show the element with class submit\n\t\tjQuery(\".submit\").show()\n\t}\n})\n\n\n// if a link with the class advanced-section-link is clicked,\n// get the data-AS-section and the data-AS-subsection values of the clicked element\n// and trigger a click on the element with the data-ssection-slug value and a click on the element with the data-subsection-slug value\njQuery(document).on(\"click\", \".advanced-section-link\", (e) => {\n\n\te.preventDefault()\n\n\tlet sectionSlug    = jQuery(e.currentTarget).data(\"as-section\")\n\tlet subsectionSlug = jQuery(e.currentTarget).data(\"as-subsection\")\n\n\tjQuery(`a[data-section-slug=${sectionSlug}]`).trigger(\"click\")\n\n\tjQuery(`ul[data-section-slug=${sectionSlug}]`).children(`[data-subsection-slug=${subsectionSlug}]`).trigger(\"click\")\n})\n","jQuery(function () {\n\n\t/**\n\t * Copy debug info to clipboard when the button is clicked.\n\t */\n\tjQuery(\"#debug-info-button\").on(\"click\", () => {\n\t\t// Select text in textarea\n\t\tconst textarea = jQuery(\"#debug-info-textarea\")[0];\n\t\ttextarea.select();\n\t\ttextarea.setSelectionRange(0, 99999); // For mobile devices\n\n\t\t// Copy selected text to clipboard\n\t\twpm.copyTextToClipboard(jQuery(\"#debug-info-textarea\").val());\n\n\t\t// Show success message and hide after 3 seconds\n\t\tconst successElement = jQuery(\"#debug-info-success\");\n\t\tsuccessElement.fadeIn(200);\n\t\tsetTimeout(() => successElement.fadeOut(200), 3000);\n\t});\n\n\tjQuery(\"#pmw-pro-version-demo\").on(\"click\", function () {\n\t\tjQuery(\"#submit\").trigger(\"click\");\n\t});\n\n\tif (document.getElementById(\"json-settings-file-input\")) {\n\t\tdocument.getElementById(\"json-settings-file-input\")\n\t\t\t.addEventListener(\"change\", wpm.readSettingsFile, false);\n\t}\n\n\t// if element ga4-data-api-credentials-upload-button exists, then we are on the GA4 settings page\n\tif (document.getElementById(\"ga4-data-api-credentials-upload-button\")) {\n\n\t\tdocument.getElementById(\"ga4-data-api-credentials-upload-button\")\n\t\t\t.addEventListener(\"change\", wpm.readGa4DataApiCredentials, false);\n\t}\n\n\t// if element ga4-data-api-credentials-upload-button exists, then we are on the GA4 settings page\n\tif (document.getElementById(\"ga4-data-api-credentials-delete-button\")) {\n\n\t\tdocument.getElementById(\"ga4-data-api-credentials-delete-button\")\n\t\t\t.addEventListener(\"click\", () => {\n\t\t\t\twpm.saveGa4DataApiCredentialsToDb({});\n\t\t\t}, false);\n\t}\n\n\t/**\n\t * Handle log files download via REST API\n\t */\n\tjQuery(\"#wgact_download_logs_zip\").on(\"click\", function(e) {\n\t\te.preventDefault();\n\t\t\n\t\tif (jQuery(this).prop(\"disabled\")) {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tconst source = jQuery(this).data(\"source\");\n\t\tconst button = jQuery(this);\n\t\tconst originalText = button.text();\n\t\t\n\t\t// Disable button and change text\n\t\tbutton.prop(\"disabled\", true).text(\"Downloading...\");\n\t\t\n\t\t// Use fetch with proper authentication\n\t\tfetch(pmwAdminApi.root + \"pmw/v1/logs/download\", {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\t\"X-WP-Nonce\": pmwAdminApi.nonce\n\t\t\t},\n\t\t\tbody: new URLSearchParams({\n\t\t\t\tsource: source\n\t\t\t}),\n\t\t\tcredentials: 'same-origin'\n\t\t})\n\t\t.then(response => {\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow new Error(`HTTP error! status: ${response.status}`);\n\t\t\t}\n\t\t\treturn response.blob();\n\t\t})\n\t\t.then(blob => {\n\t\t\t// Create download link\n\t\t\tconst url = window.URL.createObjectURL(blob);\n\t\t\tconst a = document.createElement(\"a\");\n\t\t\ta.href = url;\n\t\t\ta.download = \"pmw-logs-\" + new Date().toISOString().slice(0,19).replace(/:/g, \"-\") + \".zip\";\n\t\t\tdocument.body.appendChild(a);\n\t\t\ta.click();\n\t\t\twindow.URL.revokeObjectURL(url);\n\t\t\tdocument.body.removeChild(a);\n\t\t\t\n\t\t\t// Re-enable the button\n\t\t\tbutton.prop(\"disabled\", false).text(originalText);\n\t\t})\n\t\t.catch(error => {\n\t\t\tconsole.error(\"Download error:\", error);\n\t\t\tbutton.prop(\"disabled\", false).text(originalText);\n\t\t\talert(\"Error downloading log files. Please try again.\");\n\t\t});\n\t});\n});\n\n// jQuery(function () {\n//\n// \timport(\"../../../node_modules/@floating-ui/dom/dist/floating-ui.dom.mjs\")\n// \t\t.then(({\n// \t\t\t\t   computePosition,\n// \t\t\t\t   flip,\n// \t\t\t\t   shift,\n// \t\t\t\t   offset,\n// \t\t\tarrow,\n// \t\t\t   }) => {\n// \t\t\tconsole.log(\"computePosition: \", computePosition)\n//\n// \t\t\tconst button = document.querySelector('#button');\n// \t\t\tconst tooltip = document.querySelector('#tooltip');\n// \t\t\tconst arrowElement = document.querySelector('#arrow');\n//\n// \t\t\tcomputePosition(button, tooltip, {\n// \t\t\t\tplacement: 'top',\n// \t\t\t\tmiddleware: [\n// \t\t\t\t\toffset(6),\n// \t\t\t\t\tflip(),\n// \t\t\t\t\tshift({padding: 5}),\n// \t\t\t\t\tarrow({element: arrowElement}),\n// \t\t\t\t],\n// \t\t\t}).then(({x, y}) => {\n// \t\t\t\tObject.assign(tooltip.style, {\n// \t\t\t\t\tleft: `${x}px`,\n// \t\t\t\t\ttop: `${y}px`,\n// \t\t\t\t});\n// \t\t\t});\n//\n// \t\t})\n// \t\t.catch(err => {\n// \t\t\tconsole.error(err)\n// \t\t})\n//\n// });\n\n\n(function (wpm, $, undefined) {\n\n\twpm.saveSettingsToDisk = () => {\n\t\tlet text = document.getElementById(\"export-settings-json\").value;\n\n\t\t// Extract timestamp from the settings JSON\n\t\tlet timestamp = \"unknown\";\n\t\ttry {\n\t\t\tlet settings = JSON.parse(text);\n\t\t\tif (settings.timestamp) {\n\t\t\t\ttimestamp = settings.timestamp;\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.warn(\"Could not extract timestamp from settings:\", error);\n\t\t}\n\n\t\ttext                 = text.replace(/\\n/g, \"\\r\\n\"); // To retain the Line breaks.\n\t\tlet blob             = new Blob([text], {type: \"text/plain\"});\n\t\tlet anchor           = document.createElement(\"a\");\n\t\tanchor.download      = \"pixel-manager-settings_\" + timestamp + \"_\" + wpm.getDateTimeFromTimestamp(timestamp) + \".json\";\n\t\tanchor.href          = window.URL.createObjectURL(blob);\n\t\tanchor.target        = \"_blank\";\n\t\tanchor.style.display = \"none\"; // just to be safe!\n\t\tdocument.body.appendChild(anchor);\n\t\tanchor.click();\n\t\tdocument.body.removeChild(anchor);\n\t};\n\n\t// Get date and time from timestamp in year.month.day_hour-minute-second format. All components are zero padded.\n\t// Uses WordPress site timezone to match what's displayed on admin pages.\n\twpm.getDateTimeFromTimestamp = (timestamp) => {\n\t\t// If timestamp is \"unknown\" or invalid, fall back to current date/time\n\t\tif (timestamp === \"unknown\" || !timestamp || isNaN(timestamp)) {\n\t\t\treturn wpm.getCurrentDateForFileName();\n\t\t}\n\n\t\t// Convert Unix timestamp (seconds) to milliseconds for JavaScript Date\n\t\tlet date = new Date(timestamp * 1000);\n\n\t\t// Apply WordPress timezone offset if available\n\t\tif (pmwAdminApi && pmwAdminApi.timezone && typeof pmwAdminApi.timezone.offset === \"number\") {\n\t\t\t// Create new date in WordPress timezone by adding the offset\n\t\t\tlet wpTimezoneOffsetMs = pmwAdminApi.timezone.offset * 60 * 60 * 1000; // Convert hours to milliseconds\n\t\t\tdate                   = new Date(date.getTime() + wpTimezoneOffsetMs);\n\n\t\t\t// Get WordPress timezone date/time components using UTC methods\n\t\t\t// (since we've already applied the offset to the date object)\n\t\t\tlet year    = date.getUTCFullYear();\n\t\t\tlet month   = (\"0\" + (date.getUTCMonth() + 1)).slice(-2);\n\t\t\tlet day     = (\"0\" + date.getUTCDate()).slice(-2);\n\t\t\tlet hours   = (\"0\" + date.getUTCHours()).slice(-2);\n\t\t\tlet minutes = (\"0\" + date.getUTCMinutes()).slice(-2);\n\t\t\tlet seconds = (\"0\" + date.getUTCSeconds()).slice(-2);\n\n\t\t\treturn year + \".\" + month + \".\" + day + \"_\" + hours + \"-\" + minutes + \"-\" + seconds;\n\t\t} else {\n\t\t\t// Fallback to browser local timezone if WordPress timezone data is not available\n\t\t\tlet year    = date.getFullYear();\n\t\t\tlet month   = (\"0\" + (date.getMonth() + 1)).slice(-2);\n\t\t\tlet day     = (\"0\" + date.getDate()).slice(-2);\n\t\t\tlet hours   = (\"0\" + date.getHours()).slice(-2);\n\t\t\tlet minutes = (\"0\" + date.getMinutes()).slice(-2);\n\t\t\tlet seconds = (\"0\" + date.getSeconds()).slice(-2);\n\t\t\treturn year + \".\" + month + \".\" + day + \"_\" + hours + \"-\" + minutes + \"-\" + seconds;\n\t\t}\n\t};\n\n\t// Get current date and time in year.month.day_hour-minute-second format. All components are zero padded.\n\t// Uses WordPress site timezone to match what's displayed on admin pages.\n\twpm.getCurrentDateForFileName = () => {\n\t\tlet date = new Date();\n\n\t\t// Apply WordPress timezone offset if available\n\t\tif (pmwAdminApi && pmwAdminApi.timezone && typeof pmwAdminApi.timezone.offset === \"number\") {\n\t\t\t// Apply WordPress timezone offset\n\t\t\tlet wpTimezoneOffsetMs = pmwAdminApi.timezone.offset * 60 * 60 * 1000; // Convert hours to milliseconds\n\t\t\tdate                   = new Date(date.getTime() + wpTimezoneOffsetMs);\n\n\t\t\t// Get WordPress timezone date/time components using UTC methods\n\t\t\t// (since we've already applied the offset to the date object)\n\t\t\tlet year    = date.getUTCFullYear();\n\t\t\tlet month   = (\"0\" + (date.getUTCMonth() + 1)).slice(-2);\n\t\t\tlet day     = (\"0\" + date.getUTCDate()).slice(-2);\n\t\t\tlet hours   = (\"0\" + date.getUTCHours()).slice(-2);\n\t\t\tlet minutes = (\"0\" + date.getUTCMinutes()).slice(-2);\n\t\t\tlet seconds = (\"0\" + date.getUTCSeconds()).slice(-2);\n\n\t\t\treturn year + \".\" + month + \".\" + day + \"_\" + hours + \"-\" + minutes + \"-\" + seconds;\n\t\t} else {\n\t\t\t// Fallback to browser local timezone if WordPress timezone data is not available\n\t\t\tlet year    = date.getFullYear();\n\t\t\tlet month   = (\"0\" + (date.getMonth() + 1)).slice(-2);\n\t\t\tlet day     = (\"0\" + date.getDate()).slice(-2);\n\t\t\tlet hours   = (\"0\" + date.getHours()).slice(-2);\n\t\t\tlet minutes = (\"0\" + date.getMinutes()).slice(-2);\n\t\t\tlet seconds = (\"0\" + date.getSeconds()).slice(-2);\n\t\t\treturn year + \".\" + month + \".\" + day + \"_\" + hours + \"-\" + minutes + \"-\" + seconds;\n\t\t}\n\n\t\t// return date.toLocaleDateString(\n\t\t// \t\"en-US\", {\n\t\t// \t\tyear : \"numeric\",\n\t\t// \t\tmonth: \"2-digit\",\n\t\t// \t\tday  : \"2-digit\",\n\t\t// \t},\n\t\t// )\n\t};\n\n\twpm.readSettingsFile = e => {\n\n\t\tlet file = e.target.files[0];\n\t\tif (!file) return;\n\t\tlet reader    = new FileReader();\n\t\treader.onload = function (e) {\n\n\t\t\t// Check if the file is a valid JSON file\n\t\t\t// If it is not a valid JSON file, display an error message\n\t\t\ttry {\n\t\t\t\tJSON.parse(e.target.result);\n\t\t\t} catch (error) {\n\t\t\t\tdocument.getElementById(\"settings-upload-status-error\").style.display     = \"block\";\n\t\t\t\tdocument.getElementById(\"settings-upload-status-error-message\").innerHTML = \"Invalid JSON file.\";\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet contents = JSON.parse(e.target.result);\n\n\t\t\t// document.getElementById(\"import-settings-json\").textContent = JSON.stringify(contents)\n\n\t\t\twpm.saveImportedSettingsToDb(contents);\n\t\t};\n\t\treader.readAsText(file);\n\t};\n\n\twpm.saveImportedSettingsToDb = settings => {\n\n\t\tfetch(pmwAdminApi.root + \"pmw/v1/settings/\", {\n\t\t\tmethod     : \"POST\",\n\t\t\tcredentials: \"same-origin\",\n\t\t\theaders    : {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\"X-WP-Nonce\"  : pmwAdminApi.nonce,\n\t\t\t},\n\t\t\tbody       : JSON.stringify(settings),\n\t\t})\n\t\t\t.then(response => response.json())\n\t\t\t.then(async message => {\n\t\t\t\tif (message.success) {\n\t\t\t\t\tconsole.log(message);\n\t\t\t\t\t// reload window\n\t\t\t\t\tdocument.getElementById(\"settings-upload-status-success\").style.display = \"block\";\n\t\t\t\t\t// wait 5 seconds\n\t\t\t\t\tawait new Promise(resolve => setTimeout(resolve, 1000));\n\t\t\t\t\twindow.location.reload();\n\t\t\t\t} else {\n\t\t\t\t\tconsole.log(message);\n\t\t\t\t\tdocument.getElementById(\"settings-upload-status-error\").style.display = \"block\";\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch(error => {\n\t\t\t\tconsole.error(error);\n\t\t\t\tdocument.getElementById(\"settings-upload-status-error\").style.display = \"block\";\n\t\t\t});\n\t};\n\n\twpm.restoreBackup = (timestamp) => {\n\n\t\tconsole.log(\"restoreBackup() - timestamp: \", timestamp);\n\n\t\tfetch(pmwAdminApi.root + \"pmw/v1/options-backup/\" + timestamp + \"/restore\", {\n\t\t\tmethod     : \"POST\",\n\t\t\tcredentials: \"same-origin\",\n\t\t\theaders    : {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\"X-WP-Nonce\"  : pmwAdminApi.nonce,\n\t\t\t},\n\t\t})\n\t\t\t.then(response => response.json())\n\t\t\t.then(async message => {\n\n\t\t\t\tif (message?.data?.message) {\n\t\t\t\t\tconsole.log(\"restoreBackup() - message: \", message.data.message);\n\t\t\t\t}\n\n\t\t\t\tif (message.success) {\n\t\t\t\t\twindow.location.reload();\n\t\t\t\t} else {\n\t\t\t\t\talert(message.data.message);\n\t\t\t\t}\n\n\t\t\t})\n\t\t\t.catch(error => {\n\t\t\t\tconsole.error(error);\n\t\t\t\talert(error.message);\n\t\t\t});\n\t};\n\n\twpm.readGa4DataApiCredentials = e => {\n\n\t\tlet file = e.target.files[0];\n\t\tif (!file) return;\n\t\tlet reader    = new FileReader();\n\t\treader.onload = function (e) {\n\n\t\t\t// Check if the file is a valid JSON file\n\t\t\t// If it is not a valid JSON file, display an error message\n\t\t\ttry {\n\t\t\t\tJSON.parse(e.target.result);\n\t\t\t} catch (error) {\n\t\t\t\tdocument.getElementById(\"ga4-api-credentials-upload-status-error\").style.display     = \"block\";\n\t\t\t\tdocument.getElementById(\"ga4-api-credentials-upload-status-error-message\").innerHTML = \"Invalid JSON file.\";\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet contents = JSON.parse(e.target.result);\n\n\t\t\t// document.getElementById(\"import-settings-json\").textContent = JSON.stringify(contents)\n\n\t\t\twpm.saveGa4DataApiCredentialsToDb(contents);\n\t\t};\n\t\treader.readAsText(file);\n\t};\n\n\twpm.deleteGa4DataApiCredentials = e => {\n\t\twpm.saveGa4DataApiCredentialsToDb({});\n\t};\n\n\twpm.saveGa4DataApiCredentialsToDb = credentials => {\n\n\t\tfetch(pmwAdminApi.root + \"pmw/v1/ga4/data-api/credentials\", {\n\t\t\tmethod     : \"POST\",\n\t\t\tcredentials: \"same-origin\",\n\t\t\theaders    : {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\"X-WP-Nonce\"  : pmwAdminApi.nonce,\n\t\t\t},\n\t\t\tbody       : JSON.stringify(credentials),\n\t\t})\n\t\t\t.then(response => response.json())\n\t\t\t.then(async responseJson => {\n\t\t\t\tif (responseJson.success) {\n\t\t\t\t\tconsole.log(responseJson);\n\t\t\t\t\t// reload window\n\t\t\t\t\tdocument.getElementById(\"ga4-api-credentials-upload-status-success\").style.display = \"block\";\n\t\t\t\t\t// wait 5 seconds\n\t\t\t\t\t// await new Promise(resolve => setTimeout(resolve, 5000))\n\t\t\t\t\twindow.location.reload();\n\t\t\t\t} else {\n\t\t\t\t\tconsole.log(responseJson);\n\t\t\t\t\tdocument.getElementById(\"ga4-api-credentials-upload-status-error\").style.display     = \"block\";\n\t\t\t\t\t// and add the error message\n\t\t\t\t\tdocument.getElementById(\"ga4-api-credentials-upload-status-error-message\").innerHTML = \"Error message: \" + responseJson.data.message;\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch(error => {\n\t\t\t\tconsole.error(error);\n\t\t\t\tdocument.getElementById(\"ga4-api-credentials-upload-status-error\").style.display = \"block\";\n\t\t\t});\n\t};\n\n\twpm.getAiBotUrl = () => {\n\t\tif (pmw_cody?.url) {\n\t\t\treturn pmw_cody.url;\n\t\t}\n\t};\n\n\t/**\n\t * Opens the chatbot in a side panel (like n8n)\n\t * The panel slides in from the right side of the screen\n\t */\n\twpm.loadAiChatWindow = () => {\n\t\tconst panel = document.getElementById(\"pmw-chatbot-panel\");\n\t\tconst iframe = document.getElementById(\"pmw-chatbot-iframe\");\n\n\t\tif (!panel || !iframe) {\n\t\t\tconsole.error(\"Chatbot panel elements not found\");\n\t\t\treturn;\n\t\t}\n\n\t\t// Set the iframe source\n\t\tiframe.src = wpm.getAiBotUrl();\n\n\t\t// Add body class to push content left\n\t\tdocument.body.classList.add(\"pmw-chatbot-open\");\n\n\t\t// Open the panel\n\t\tpanel.classList.add(\"pmw-chatbot-panel-open\");\n\t};\n\n\t/**\n\t * Closes the chatbot side panel\n\t */\n\twpm.closeChatbot = () => {\n\t\tconst panel = document.getElementById(\"pmw-chatbot-panel\");\n\t\tif (panel) {\n\t\t\tpanel.classList.remove(\"pmw-chatbot-panel-open\");\n\t\t\t// Remove body class to restore content position\n\t\t\tdocument.body.classList.remove(\"pmw-chatbot-open\");\n\t\t}\n\t};\n\n\t/**\n\t * Check if the Cody AI chatbot is available.\n\t *\n\t * @return {boolean}\n\t */\n\twpm.codyAvailable = () => {\n\t\tif (typeof window.pmw_cody !== \"undefined\" && window.pmw_cody?.available) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t};\n\n\t// Schedule a recalculation of the LTV by sending a POST REST request to the server\n\twpm.ltvRecalculation = event => {\n\n\t\tconst displayStatusMessage = (message) => {\n\t\t\tlet elements = document.getElementsByClassName(\"ltv-message\");\n\t\t\tfor (let i = 0; i < elements.length; i++) {\n\t\t\t\telements[i].style.display = \"none\";\n\t\t\t}\n\t\t\tdocument.getElementById(\"ltv-message-error\").style.display  = \"block\";\n\t\t\tdocument.getElementById(\"ltv-message-error-text\").innerHTML = message;\n\t\t};\n\n\t\tconst displayRunImmediatelyButton = () => {\n\t\t\tlet elements = document.getElementsByClassName(\"ltv-button-text\");\n\t\t\tfor (let i = 0; i < elements.length; i++) {\n\t\t\t\telements[i].style.display = \"none\";\n\t\t\t}\n\t\t\tdocument.getElementById(\"ltv-instant-recalculation-button-text\").style.display = \"block\";\n\t\t};\n\n\t\tconst removeAllMessages = () => {\n\t\t\tlet elements = document.getElementsByClassName(\"ltv-message\");\n\t\t\tfor (let i = 0; i < elements.length; i++) {\n\t\t\t\telements[i].style.display = \"none\";\n\t\t\t}\n\n\t\t\tdocument.getElementById(\"ltv-message-error\").style.display = \"none\";\n\t\t};\n\n\t\t// console log the data-action from the nested span element of the clicked element\n\t\t// console.log(\"event.target.dataset.action\", event.target.dataset.action)\n\n\t\tfetch(pmwAdminApi.root + \"pmw/v1/ltv/\", {\n\t\t\tmethod     : \"POST\",\n\t\t\tcredentials: \"same-origin\",\n\t\t\theaders    : {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\"X-WP-Nonce\"  : pmwAdminApi.nonce,\n\t\t\t},\n\t\t\tbody       : JSON.stringify({\n\t\t\t\t\"action\": event.target.dataset.action,\n\t\t\t}),\n\t\t})\n\t\t\t.then(response => response.json())\n\t\t\t.then(message => {\n\t\t\t\tif (message.success) {\n\t\t\t\t\tconsole.log(message);\n\t\t\t\t\t// reload window\n\n\t\t\t\t\tif (message.data.status.is_scheduled) {\n\t\t\t\t\t\tremoveAllMessages();\n\t\t\t\t\t\tdisplayRunImmediatelyButton();\n\t\t\t\t\t\tdocument.getElementById(\"ltv-schedule-recalculation-confirmation-message\").style.display = \"block\";\n\t\t\t\t\t}\n\n\t\t\t\t\tif (message.data.status.is_running) {\n\t\t\t\t\t\t// Get the button element with the id \"wgact_ltv_recalculation\" and disable it\n\t\t\t\t\t\tdocument.getElementById(\"wgact_ltv_recalculation\").disabled = true;\n\t\t\t\t\t\tremoveAllMessages();\n\t\t\t\t\t\tdocument.getElementById(\"ltv-running-recalculation-confirmation-message\").style.display = \"block\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// if is neither message.data.status.is_running nor message.data.status.is_scheduled\n\t\t\t\t\t// then display the error message\n\t\t\t\t\tif (!message.data.status.is_running && !message.data.status.is_scheduled) {\n\t\t\t\t\t\tdisplayStatusMessage(message.data.message);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tconsole.error(message);\n\t\t\t\t\tdisplayStatusMessage(message.data.message);\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch(error => {\n\t\t\t\tconsole.error(error);\n\t\t\t\tdisplayStatusMessage(error);\n\t\t\t});\n\t};\n\n\twpm.copyTextToClipboard = (text) => {\n\t\tnavigator.clipboard.writeText(text)\n\t\t\t.catch(err => {\n\t\t\t\tconsole.error(\"Failed to copy: \", err);\n\t\t\t});\n\t};\n\n}(window.wpm = window.wpm || {}, jQuery));\n\n/**\n * This script listens for the DOMContentLoaded event. Once the DOM is fully loaded,\n * it checks if the chatbot (wpm.codyAvailable()) is available.\n * If the chatbot is available, it displays the chat widget button.\n * If the chatbot is not available, it logs a message to the console indicating that the chatbot is unavailable.\n *\n * @listens document#DOMContentLoaded\n */\ndocument.addEventListener(\"DOMContentLoaded\", () => {\n\n\tif (wpm.codyAvailable()) {\n\t\tconst chatbotWidget = document.getElementById(\"pmw-chatbot-widget\");\n\t\tif (chatbotWidget) {\n\t\t\tchatbotWidget.style.display = \"block\";\n\t\t}\n\n\t\t// Show the chatbot line in the support section\n\t\tconst chatbotListItem = document.getElementById(\"pmw-chat-li\");\n\t\tif (chatbotListItem) {\n\t\t\tchatbotListItem.style.display = \"list-item\";\n\t\t}\n\n\t\t// Set up event listeners for the chatbot widget\n\t\tconst chatbotToggle = document.getElementById(\"pmw-chatbot-toggle\");\n\t\tconst chatbotClose = document.getElementById(\"pmw-chatbot-close\");\n\n\t\tif (chatbotToggle) {\n\t\t\tchatbotToggle.addEventListener(\"click\", (e) => {\n\t\t\t\te.preventDefault();\n\t\t\t\twpm.loadAiChatWindow();\n\t\t\t});\n\t\t}\n\n\t\tif (chatbotClose) {\n\t\t\tchatbotClose.addEventListener(\"click\", (e) => {\n\t\t\t\te.preventDefault();\n\t\t\t\twpm.closeChatbot();\n\t\t\t});\n\t\t}\n\n\t\t// Close chatbot on ESC key\n\t\tdocument.addEventListener(\"keydown\", (event) => {\n\t\t\tif (event.key === \"Escape\") {\n\t\t\t\twpm.closeChatbot();\n\t\t\t}\n\t\t});\n\t} else {\n\t\tconsole.log(\"DOMContentLoaded - chatbot is not available\");\n\t}\n\n}, true);\n\n// Wait until the DOM is loaded, then console log\n// the message \"DOMContentLoaded - chatbot is not available\"\n// use jquery\njQuery(() => {\n\tif (document.querySelector(\"#wgact_ltv_recalculation\")) {\n\t\tdocument.querySelector(\"#wgact_ltv_recalculation\").addEventListener(\"click\", event => {\n\t\t\tevent.preventDefault();\n\t\t\twpm.ltvRecalculation(event);\n\t\t});\n\t}\n\n\tif (document.querySelector(\"#pmw_stop_ltv_calculation\")) {\n\t\tdocument.querySelector(\"#pmw_stop_ltv_calculation\").addEventListener(\"click\", event => {\n\t\t\tevent.preventDefault();\n\t\t\twpm.ltvRecalculation(event);\n\t\t});\n\t}\n\n\t// Add event listeners for backup restore buttons\n\tjQuery(() => {\n\t\tjQuery(document).on(\"click\", \".pmw-restore-backup-button\", function (event) {\n\t\t\tevent.preventDefault();\n\t\t\tconst timestamp = jQuery(this).data(\"timestamp\");\n\t\t\tif (timestamp) {\n\t\t\t\twpm.restoreBackup(timestamp);\n\t\t\t}\n\t\t});\n\t});\n});\n\n/**\n * add an event listener to the button with the id \"wgact_copy_log_file_links\"\n * when the button is clicked, copy the log file links to the clipboard\n * the data-links attribute of the button contains a json string with the links\n */\njQuery(() => {\n\n\tif (!document.querySelector(\"#wgact_copy_log_file_links\")) {\n\t\treturn;\n\t}\n\n\tdocument.querySelector(\"#wgact_copy_log_file_links\").addEventListener(\"click\", event => {\n\t\tevent.preventDefault();\n\n\t\tconst jsonOfLinks = JSON.parse(event.target.dataset.links);\n\n\t\tlet strOfLinks = \"\";\n\n\t\tfor (let i = 0, len = jsonOfLinks.length; i < len; i++) {\n\t\t\tstrOfLinks += jsonOfLinks[i] + \"\\n\";\n\t\t}\n\n\t\twpm.copyTextToClipboard(strOfLinks);\n\n\t\t// make the button text change to \"Copied!\" and keep the same width and text for 3 seconds\n\t\tlet button         = document.getElementById(\"wgact_copy_log_file_links\");\n\t\tbutton.style.width = getComputedStyle(button).width;\n\t\tconst originalText = button.innerHTML;\n\t\tbutton.innerHTML   = event.target.dataset.textCopied;\n\t\tsetTimeout(function () {\n\t\t\tbutton.innerHTML = originalText;\n\t\t}, 3000);\n\t});\n});\n\n// on pressing enter in form inputs, click the submit button\njQuery(() => {\n\tjQuery(document).on(\"keydown\", \"input, textarea, select\", function (event) {\n\t\tif (event.key === \"Enter\" && !event.shiftKey && !event.ctrlKey && !event.altKey) {\n\t\t\t// Only trigger submit if we're in a form and not in a textarea (where Enter should create new lines)\n\t\t\tconst $target = jQuery(event.target);\n\t\t\tif ($target.is(\"input\") && $target.closest(\"form\").length > 0) {\n\t\t\t\tconst form = $target.closest(\"form\")[0];\n\t\t\t\tconst submitButton = jQuery(form).find(\"#submit\");\n\t\t\t\tif (submitButton.length > 0) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tsubmitButton.click();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n});\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","/**\n * Combine all admin scripts\n * (which only run on the wpm pages)\n */\n\n// require(\"./environment-check\")\nrequire(\"./helpers\")\nrequire(\"./script-blocker-warning\")\nrequire(\"./tabs\")\n\n// #if process.env.TIER === 'premium'\n// // require(\"./helpers_premium\")\n// #endif\n\n// console.log('Pixel Manager for WooCommerce admin script')\n"],"names":["wpm_hide_script_blocker_warning","jQuery","hide","wpmGetPageId","sections","subsections","closest","each","push","this","data","forEach","section","badge","append","after","wpmCreateSubtabUlHtml","on","e","preventDefault","addClass","siblings","removeClass","sectionSlug","wpmToggleSections","children","trigger","stopPropagation","wpmToggleSubsection","parent","wpmGetSectionParams","sectionParams","subsectionsKeys","Object","keys","html","subsectionKey","subtab","queryString","window","location","search","urlParams","URLSearchParams","get","nextUntil","andSelf","show","sectionPos","findIndex","arrayElement","prevAll","next","wpmSetUrl","subsectionSlug","delete","newParams","history","pushState","document","pathname","val","wpmGetAdminPath","URL","attr","includes","currentTarget","textarea","select","setSelectionRange","wpm","copyTextToClipboard","successElement","fadeIn","setTimeout","fadeOut","getElementById","addEventListener","readSettingsFile","readGa4DataApiCredentials","saveGa4DataApiCredentialsToDb","prop","source","button","originalText","text","fetch","pmwAdminApi","root","method","headers","nonce","body","credentials","then","response","ok","Error","status","blob","url","createObjectURL","a","createElement","href","download","Date","toISOString","slice","replace","appendChild","click","revokeObjectURL","removeChild","catch","error","console","alert","saveSettingsToDisk","value","timestamp","settings","JSON","parse","warn","Blob","type","anchor","getDateTimeFromTimestamp","target","style","display","isNaN","getCurrentDateForFileName","date","timezone","offset","wpTimezoneOffsetMs","getTime","getUTCFullYear","getUTCMonth","getUTCDate","getUTCHours","getUTCMinutes","getUTCSeconds","getFullYear","getMonth","getDate","getHours","getMinutes","getSeconds","file","files","reader","FileReader","onload","result","innerHTML","contents","saveImportedSettingsToDb","readAsText","stringify","json","async","message","success","log","Promise","resolve","reload","restoreBackup","deleteGa4DataApiCredentials","responseJson","getAiBotUrl","pmw_cody","loadAiChatWindow","panel","iframe","src","classList","add","closeChatbot","remove","codyAvailable","available","ltvRecalculation","event","displayStatusMessage","elements","getElementsByClassName","i","length","removeAllMessages","dataset","action","is_scheduled","displayRunImmediatelyButton","is_running","disabled","navigator","clipboard","writeText","err","chatbotWidget","chatbotListItem","chatbotToggle","chatbotClose","key","querySelector","jsonOfLinks","links","strOfLinks","len","width","getComputedStyle","textCopied","shiftKey","ctrlKey","altKey","$target","is","form","submitButton","find","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","exports","module","__webpack_modules__","require"],"ignoreList":[],"sourceRoot":""}
  • woocommerce-google-adwords-conversion-tracking-tag/trunk/js/public/free/consent-api.12d29397.chunk.min.js.map

    r3396512 r3420138  
    1 {"version":3,"file":"consent-api.12d29397.chunk.min.js","mappings":";gSAWO,MAAMA,EAAY,EAAEC,WAAW,MAAQ,CAAC,KAE9C,MAAMC,EAAO,CACZC,YAAa,EACbC,WAAa,EACbC,aAAa,EACbC,WAAa,EACbL,SAAaA,GAGdM,EAAUL,GACVM,IACAC,SAASC,cAAc,IAAIC,YAAY,qBAAsB,CAACC,OAAQV,MAU1DW,EAAY,EAAEZ,WAAW,MAAQ,CAAC,KAE9C,MAAMC,EAAO,CACZC,YAAa,EACbC,WAAa,EACbC,aAAa,EACbC,WAAa,EACbL,SAAaA,GAGdM,EAAUL,GACVO,SAASC,cAAc,IAAIC,YAAY,qBAAsB,CAACC,OAAQV,MAc1DY,EAAoB,EACtBX,aAAaY,IAAIC,QAAQC,WAAWC,MAAMf,WAC1CC,YAAYW,IAAIC,QAAQC,WAAWC,MAAMd,UACzCC,cAAcU,IAAIC,QAAQC,WAAWC,MAAMb,YAC3CC,YAAYS,IAAIC,QAAQC,WAAWC,MAAMZ,UACzCL,WAAW,cAGFkB,IAAfhB,QAA0CgB,IAAdf,QAA2Ce,IAAhBd,QAA2Cc,IAAdb,GACvFc,QAAQC,IAAI,wHAGb,IAAInB,EAAO,CACVC,aACAC,YACAC,cACAC,YACAL,YAGDM,EAAUL,GACVM,IACAC,SAASC,cAAc,IAAIC,YAAY,qBAAsB,CAACC,OAAQV,MAkCjEM,EAAqB,KAC1BC,SAASC,cAAc,IAAIY,MAAM,qBAU5Bf,EAAaL,IAClBa,IAAIC,QAAQC,WAAWM,IAAIrB,GA3BH,GAAEC,aAAYC,YAAWC,cAAaC,YAAWL,WAAW,SAEpF,MACMC,EAAO,CAACC,aAAYC,YAAWC,cAAaC,aAIjC,OAAbL,EAKJc,IAAIS,UAAU,qBAAsBC,KAAKC,UAAUxB,GAAOD,GAJzDc,IAAIY,UANQ,qBAMOzB,GAAM,IAoB1B0B,CAAiB1B,GACjB2B,IAAIT,QAAQC,IAAI,wBAAyBnB,IAU7B4B,EAAgDC,IAE5D,GAAsB,YAAlBA,EAAW,GAAkB,OACjC,GAAsB,WAAlBA,EAAW,GAAiB,OAChC,GAA8B,QAA1BA,EAAW,IAAIC,OAAkB,OAErCH,IAAIT,QAAQC,IAAI,kCAAmCU,GAEnD,IAAIE,EAAelB,IAAIC,QAAQC,WAAWC,MAEtChB,EAAO,CACVC,gBAAiDgB,IAApCY,EAAW,GAAGG,kBAAsE,YAApCH,EAAW,GAAGG,kBAAkCD,EAAa9B,WAC1HC,eAA0Ce,IAA7BY,EAAW,GAAGI,WAAwD,YAA7BJ,EAAW,GAAGI,WAA2BF,EAAa7B,UAC5GC,kBAAsDc,IAAxCY,EAAW,GAAGK,sBAA8E,YAAxCL,EAAW,GAAGK,sBAAsCH,EAAa5B,oBACvFc,IAA1CY,EAAW,GAAGM,wBAAkF,YAA1CN,EAAW,GAAGM,wBAAwCJ,EAAa5B,aAC3HC,eAAgDa,IAAnCY,EAAW,GAAGO,iBAAoE,YAAnCP,EAAW,GAAGO,iBAAiCL,EAAa3B,WAGzHC,EAAUL,GACVM,KAGY+B,EAAsBC,GAC3BzB,IAAIC,QAAQC,WAAWC,MAAMsB,E","sources":["webpack://Pixel-Manager-for-WooCommerce/./src/js-src/public/wpm/consent/api.mjs"],"sourcesContent":["/**\n * Pixel Manager Cookie Consent API\n **/\n\n/**\n * Accept consent for all cookies\n *\n * @param duration {number|null}\n * @returns {void}\n * @public\n */\nexport const acceptAll = ({duration = null} = {}) => {\n\n\tconst data = {\n\t\tstatistics : true,\n\t\tmarketing  : true,\n\t\tpreferences: true,\n\t\tnecessary  : true,\n\t\tduration   : duration,\n\t};\n\n\tsaveState(data);\n\tloadApprovedPixels();\n\tdocument.dispatchEvent(new CustomEvent(\"pmw:consent:update\", {detail: data}));\n};\n\n/**\n * Revoke consent for all cookies\n *\n * @param duration {number|null}\n * @returns {void}\n * @public\n */\nexport const revokeAll = ({duration = null} = {}) => {\n\n\tconst data = {\n\t\tstatistics : false,\n\t\tmarketing  : false,\n\t\tpreferences: false,\n\t\tnecessary  : true,\n\t\tduration   : duration,\n\t};\n\n\tsaveState(data);\n\tdocument.dispatchEvent(new CustomEvent(\"pmw:consent:update\", {detail: data}));\n};\n\n/**\n * Accept consent selectively\n *\n * @param statistics\n * @param marketing\n * @param preferences\n * @param necessary\n * @param duration\n * @returns {void}\n * @public\n */\nexport const updateSelectively = ({\n\t\t\t\t\t\t\t\t\t  statistics = wpm.consent.categories.get().statistics,\n\t\t\t\t\t\t\t\t\t  marketing = wpm.consent.categories.get().marketing,\n\t\t\t\t\t\t\t\t\t  preferences = wpm.consent.categories.get().preferences,\n\t\t\t\t\t\t\t\t\t  necessary = wpm.consent.categories.get().necessary,\n\t\t\t\t\t\t\t\t\t  duration = null,\n\t\t\t\t\t\t\t\t  }) => {\n\n\tif (statistics === undefined || marketing === undefined || preferences === undefined || necessary === undefined) {\n\t\tconsole.log(\"pmw.consent.api.updateSelectively: It is recommended to pass all consent types. - statistics, marketing, preferences\");\n\t}\n\n\tlet data = {\n\t\tstatistics,\n\t\tmarketing,\n\t\tpreferences,\n\t\tnecessary,\n\t\tduration,\n\t};\n\n\tsaveState(data);\n\tloadApprovedPixels();\n\tdocument.dispatchEvent(new CustomEvent(\"pmw:consent:update\", {detail: data}));\n};\n\n/**\n * Set a cookie called pmw_cookie_consent with the value of pmw_cookie_consent\n * and set the default expiration date to 1 year from now.\n *\n * @param statistics {boolean}\n * @param marketing {boolean}\n * @param preferences {boolean}\n * @param necessary {boolean}\n * @param duration {number|null}\n *\n * @returns {void}\n * @private\n *\n * TODO: Use the data store\n * TODO: Cleanup\n */\nconst setConsentCookie = ({statistics, marketing, preferences, necessary, duration = null}) => {\n\n\tconst key  = \"pmw_cookie_consent\";\n\tconst data = {statistics, marketing, preferences, necessary};\n\n\t// If no duration is set, use the wpm storage,\n\t// otherwise use wpm.setCookie()\n\tif (duration === null) {\n\t\twpm.storeData(key, data, true);\n\t\treturn;\n\t}\n\n\twpm.setCookie(\"pmw_cookie_consent\", JSON.stringify(data), duration);\n};\n\nconst loadApprovedPixels = () => {\n\tdocument.dispatchEvent(new Event(\"pmw:load-pixels\"));\n};\n\n/**\n * Save the consent in the settings and set the cookie\n *\n * @param data\n * @returns {void}\n * @private\n */\nconst saveState = (data) => {\n\twpm.consent.categories.set(data);\n\tsetConsentCookie(data);\n\tpmw.console.log(\"Updated consent state\", data);\n};\n\n/**\n * Process the consent update from the external source\n *\n * @param attributes\n * @returns {void}\n * @public\n */\nexport const processExternalGcmConsentUpdate_experimental = (attributes) => {\n\n\tif (attributes[0] !== \"consent\") return;\n\tif (attributes[1] !== \"update\") return;\n\tif (attributes[2]?.source === \"pmw\") return;\n\n\tpmw.console.log(\"processExternalGcmConsentUpdate\", attributes);\n\n\tlet previousData = wpm.consent.categories.get();\n\n\tlet data = {\n\t\tstatistics : attributes[2].analytics_storage !== undefined ? attributes[2].analytics_storage === \"granted\" : previousData.statistics,\n\t\tmarketing  : attributes[2].ad_storage !== undefined ? attributes[2].ad_storage === \"granted\" : previousData.marketing,\n\t\tpreferences: (attributes[2].functionality_storage !== undefined ? attributes[2].functionality_storage === \"granted\" : previousData.preferences) ||\n\t\t\t(attributes[2].personalization_storage !== undefined ? attributes[2].personalization_storage === \"granted\" : previousData.preferences),\n\t\tnecessary  : attributes[2].security_storage !== undefined ? attributes[2].security_storage === \"granted\" : previousData.necessary,\n\t};\n\n\tsaveState(data);\n\tloadApprovedPixels();\n};\n\nexport const getConsentStateFor = (category) => {\n\treturn wpm.consent.categories.get()[category];\n};\n\n"],"names":["acceptAll","duration","data","statistics","marketing","preferences","necessary","saveState","loadApprovedPixels","document","dispatchEvent","CustomEvent","detail","revokeAll","updateSelectively","wpm","consent","categories","get","undefined","console","log","Event","set","setCookie","JSON","stringify","storeData","setConsentCookie","pmw","processExternalGcmConsentUpdate_experimental","attributes","source","previousData","analytics_storage","ad_storage","functionality_storage","personalization_storage","security_storage","getConsentStateFor","category"],"sourceRoot":""}
     1{"version":3,"file":"consent-api.12d29397.chunk.min.js","mappings":";gSAWO,MAAMA,EAAY,EAAEC,WAAW,MAAQ,CAAC,KAE9C,MAAMC,EAAO,CACZC,YAAa,EACbC,WAAa,EACbC,aAAa,EACbC,WAAa,EACbL,SAAaA,GAGdM,EAAUL,GACVM,IACAC,SAASC,cAAc,IAAIC,YAAY,qBAAsB,CAACC,OAAQV,MAU1DW,EAAY,EAAEZ,WAAW,MAAQ,CAAC,KAE9C,MAAMC,EAAO,CACZC,YAAa,EACbC,WAAa,EACbC,aAAa,EACbC,WAAa,EACbL,SAAaA,GAGdM,EAAUL,GACVO,SAASC,cAAc,IAAIC,YAAY,qBAAsB,CAACC,OAAQV,MAc1DY,EAAoB,EACtBX,aAAaY,IAAIC,QAAQC,WAAWC,MAAMf,WAC1CC,YAAYW,IAAIC,QAAQC,WAAWC,MAAMd,UACzCC,cAAcU,IAAIC,QAAQC,WAAWC,MAAMb,YAC3CC,YAAYS,IAAIC,QAAQC,WAAWC,MAAMZ,UACzCL,WAAW,cAGFkB,IAAfhB,QAA0CgB,IAAdf,QAA2Ce,IAAhBd,QAA2Cc,IAAdb,GACvFc,QAAQC,IAAI,wHAGb,IAAInB,EAAO,CACVC,aACAC,YACAC,cACAC,YACAL,YAGDM,EAAUL,GACVM,IACAC,SAASC,cAAc,IAAIC,YAAY,qBAAsB,CAACC,OAAQV,MAkCjEM,EAAqB,KAC1BC,SAASC,cAAc,IAAIY,MAAM,qBAU5Bf,EAAaL,IAClBa,IAAIC,QAAQC,WAAWM,IAAIrB,GA3BH,GAAEC,aAAYC,YAAWC,cAAaC,YAAWL,WAAW,SAEpF,MACMC,EAAO,CAACC,aAAYC,YAAWC,cAAaC,aAIjC,OAAbL,EAKJc,IAAIS,UAAU,qBAAsBC,KAAKC,UAAUxB,GAAOD,GAJzDc,IAAIY,UANQ,qBAMOzB,GAAM,IAoB1B0B,CAAiB1B,GACjB2B,IAAIT,QAAQC,IAAI,wBAAyBnB,IAU7B4B,EAAgDC,IAE5D,GAAsB,YAAlBA,EAAW,GAAkB,OACjC,GAAsB,WAAlBA,EAAW,GAAiB,OAChC,GAA8B,QAA1BA,EAAW,IAAIC,OAAkB,OAErCH,IAAIT,QAAQC,IAAI,kCAAmCU,GAEnD,IAAIE,EAAelB,IAAIC,QAAQC,WAAWC,MAEtChB,EAAO,CACVC,gBAAiDgB,IAApCY,EAAW,GAAGG,kBAAsE,YAApCH,EAAW,GAAGG,kBAAkCD,EAAa9B,WAC1HC,eAA0Ce,IAA7BY,EAAW,GAAGI,WAAwD,YAA7BJ,EAAW,GAAGI,WAA2BF,EAAa7B,UAC5GC,kBAAsDc,IAAxCY,EAAW,GAAGK,sBAA8E,YAAxCL,EAAW,GAAGK,sBAAsCH,EAAa5B,oBACvFc,IAA1CY,EAAW,GAAGM,wBAAkF,YAA1CN,EAAW,GAAGM,wBAAwCJ,EAAa5B,aAC3HC,eAAgDa,IAAnCY,EAAW,GAAGO,iBAAoE,YAAnCP,EAAW,GAAGO,iBAAiCL,EAAa3B,WAGzHC,EAAUL,GACVM,KAGY+B,EAAsBC,GAC3BzB,IAAIC,QAAQC,WAAWC,MAAMsB,E","sources":["webpack://Pixel-Manager-for-WooCommerce/./src/js-src/public/wpm/consent/api.mjs"],"sourcesContent":["/**\n * Pixel Manager Cookie Consent API\n **/\n\n/**\n * Accept consent for all cookies\n *\n * @param duration {number|null}\n * @returns {void}\n * @public\n */\nexport const acceptAll = ({duration = null} = {}) => {\n\n\tconst data = {\n\t\tstatistics : true,\n\t\tmarketing  : true,\n\t\tpreferences: true,\n\t\tnecessary  : true,\n\t\tduration   : duration,\n\t};\n\n\tsaveState(data);\n\tloadApprovedPixels();\n\tdocument.dispatchEvent(new CustomEvent(\"pmw:consent:update\", {detail: data}));\n};\n\n/**\n * Revoke consent for all cookies\n *\n * @param duration {number|null}\n * @returns {void}\n * @public\n */\nexport const revokeAll = ({duration = null} = {}) => {\n\n\tconst data = {\n\t\tstatistics : false,\n\t\tmarketing  : false,\n\t\tpreferences: false,\n\t\tnecessary  : true,\n\t\tduration   : duration,\n\t};\n\n\tsaveState(data);\n\tdocument.dispatchEvent(new CustomEvent(\"pmw:consent:update\", {detail: data}));\n};\n\n/**\n * Accept consent selectively\n *\n * @param statistics\n * @param marketing\n * @param preferences\n * @param necessary\n * @param duration\n * @returns {void}\n * @public\n */\nexport const updateSelectively = ({\n\t\t\t\t\t\t\t\t\t  statistics = wpm.consent.categories.get().statistics,\n\t\t\t\t\t\t\t\t\t  marketing = wpm.consent.categories.get().marketing,\n\t\t\t\t\t\t\t\t\t  preferences = wpm.consent.categories.get().preferences,\n\t\t\t\t\t\t\t\t\t  necessary = wpm.consent.categories.get().necessary,\n\t\t\t\t\t\t\t\t\t  duration = null,\n\t\t\t\t\t\t\t\t  }) => {\n\n\tif (statistics === undefined || marketing === undefined || preferences === undefined || necessary === undefined) {\n\t\tconsole.log(\"pmw.consent.api.updateSelectively: It is recommended to pass all consent types. - statistics, marketing, preferences\");\n\t}\n\n\tlet data = {\n\t\tstatistics,\n\t\tmarketing,\n\t\tpreferences,\n\t\tnecessary,\n\t\tduration,\n\t};\n\n\tsaveState(data);\n\tloadApprovedPixels();\n\tdocument.dispatchEvent(new CustomEvent(\"pmw:consent:update\", {detail: data}));\n};\n\n/**\n * Set a cookie called pmw_cookie_consent with the value of pmw_cookie_consent\n * and set the default expiration date to 1 year from now.\n *\n * @param statistics {boolean}\n * @param marketing {boolean}\n * @param preferences {boolean}\n * @param necessary {boolean}\n * @param duration {number|null}\n *\n * @returns {void}\n * @private\n *\n * TODO: Use the data store\n * TODO: Cleanup\n */\nconst setConsentCookie = ({statistics, marketing, preferences, necessary, duration = null}) => {\n\n\tconst key  = \"pmw_cookie_consent\";\n\tconst data = {statistics, marketing, preferences, necessary};\n\n\t// If no duration is set, use the wpm storage,\n\t// otherwise use wpm.setCookie()\n\tif (duration === null) {\n\t\twpm.storeData(key, data, true);\n\t\treturn;\n\t}\n\n\twpm.setCookie(\"pmw_cookie_consent\", JSON.stringify(data), duration);\n};\n\nconst loadApprovedPixels = () => {\n\tdocument.dispatchEvent(new Event(\"pmw:load-pixels\"));\n};\n\n/**\n * Save the consent in the settings and set the cookie\n *\n * @param data\n * @returns {void}\n * @private\n */\nconst saveState = (data) => {\n\twpm.consent.categories.set(data);\n\tsetConsentCookie(data);\n\tpmw.console.log(\"Updated consent state\", data);\n};\n\n/**\n * Process the consent update from the external source\n *\n * @param attributes\n * @returns {void}\n * @public\n */\nexport const processExternalGcmConsentUpdate_experimental = (attributes) => {\n\n\tif (attributes[0] !== \"consent\") return;\n\tif (attributes[1] !== \"update\") return;\n\tif (attributes[2]?.source === \"pmw\") return;\n\n\tpmw.console.log(\"processExternalGcmConsentUpdate\", attributes);\n\n\tlet previousData = wpm.consent.categories.get();\n\n\tlet data = {\n\t\tstatistics : attributes[2].analytics_storage !== undefined ? attributes[2].analytics_storage === \"granted\" : previousData.statistics,\n\t\tmarketing  : attributes[2].ad_storage !== undefined ? attributes[2].ad_storage === \"granted\" : previousData.marketing,\n\t\tpreferences: (attributes[2].functionality_storage !== undefined ? attributes[2].functionality_storage === \"granted\" : previousData.preferences) ||\n\t\t\t(attributes[2].personalization_storage !== undefined ? attributes[2].personalization_storage === \"granted\" : previousData.preferences),\n\t\tnecessary  : attributes[2].security_storage !== undefined ? attributes[2].security_storage === \"granted\" : previousData.necessary,\n\t};\n\n\tsaveState(data);\n\tloadApprovedPixels();\n};\n\nexport const getConsentStateFor = (category) => {\n\treturn wpm.consent.categories.get()[category];\n};\n\n"],"names":["acceptAll","duration","data","statistics","marketing","preferences","necessary","saveState","loadApprovedPixels","document","dispatchEvent","CustomEvent","detail","revokeAll","updateSelectively","wpm","consent","categories","get","undefined","console","log","Event","set","setCookie","JSON","stringify","storeData","setConsentCookie","pmw","processExternalGcmConsentUpdate_experimental","attributes","source","previousData","analytics_storage","ad_storage","functionality_storage","personalization_storage","security_storage","getConsentStateFor","category"],"ignoreList":[],"sourceRoot":""}
  • woocommerce-google-adwords-conversion-tracking-tag/trunk/js/public/free/consent-management.414e6bb6.chunk.min.js.map

    r3396512 r3420138  
    1 {"version":3,"file":"consent-management.414e6bb6.chunk.min.js","mappings":"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","sources":["webpack://Pixel-Manager-for-WooCommerce/./src/js-src/public/wpm/consent/cmps/borlabs.mjs","webpack://Pixel-Manager-for-WooCommerce/./src/js-src/public/wpm/consent/cmps/complianz.mjs","webpack://Pixel-Manager-for-WooCommerce/./src/js-src/public/wpm/consent/cmps/cookiebot.mjs","webpack://Pixel-Manager-for-WooCommerce/./src/js-src/public/wpm/consent/cmps/cookiefirst.mjs","webpack://Pixel-Manager-for-WooCommerce/./src/js-src/public/wpm/consent/cmps/cookieyes.mjs","webpack://Pixel-Manager-for-WooCommerce/./src/js-src/public/wpm/consent/cmps/onetrust.mjs","webpack://Pixel-Manager-for-WooCommerce/./src/js-src/public/wpm/consent/cmps/real-cookie-banner.mjs","webpack://Pixel-Manager-for-WooCommerce/./src/js-src/public/wpm/consent/cmps.mjs","webpack://Pixel-Manager-for-WooCommerce/./src/js-src/public/wpm/consent/cmps/cookie-compliance.mjs","webpack://Pixel-Manager-for-WooCommerce/./src/js-src/public/wpm/consent/cmps/cookie-script.mjs","webpack://Pixel-Manager-for-WooCommerce/./src/js-src/public/wpm/consent/cmps/iubenda.mjs","webpack://Pixel-Manager-for-WooCommerce/./src/js-src/public/wpm/consent/cmps/moove-cookie-compliance.mjs","webpack://Pixel-Manager-for-WooCommerce/./src/js-src/public/wpm/consent/cmps/termly.mjs","webpack://Pixel-Manager-for-WooCommerce/./src/js-src/public/wpm/consent/cmps/usercentrics.mjs","webpack://Pixel-Manager-for-WooCommerce/./src/js-src/public/wpm/consent/cmps/wp-auto-terms.mjs","webpack://Pixel-Manager-for-WooCommerce/./src/js-src/public/wpm/consent/cmps/wp-consent-api.mjs","webpack://Pixel-Manager-for-WooCommerce/./src/js-src/public/wpm/consent/cmps/wp-cookie-consent.mjs","webpack://Pixel-Manager-for-WooCommerce/./src/js-src/public/wpm/consent/consent.mjs"],"sourcesContent":["/**\n * Borlabs Cookie\n *\n * The PMW only