���� JFIF    �� �        "" $(4,$&1'-=-157:::#+?D?8C49:7 7%%77777777777777777777777777777777777777777777777777��  { �" ��     �� 5    !1AQa"q�2��BR��#b�������  ��  ��   ? ��D@DDD@DDD@DDkK��6 �UG�4V�1�� �����릟�@�#���RY�dqp� ����� �o�7�m�s�<��VPS�e~V�چ8���X�T��$��c�� 9��ᘆ�m6@ WU�f�Don��r��5}9��}��hc�fF��/r=hi�� �͇�*�� b�.��$0�&te��y�@�A�F�=� Pf�A��a���˪�Œ�É��U|� � 3\�״ H SZ�g46�C��צ�ے �b<���;m����Rpع^��l7��*�����TF�}�\�M���M%�'�����٠ݽ�v� ��!-�����?�N!La��A+[`#���M����'�~oR�?��v^)��=��h����A��X�.���˃����^Ə��ܯsO"B�c>; �e�4��5�k��/CB��.  �J?��;�҈�������������������~�<�VZ�ꭼ2/)Í”jC���ע�V�G�!���!�F������\�� Kj�R�oc�h���:Þ I��1"2�q×°8��Р@ז���_C0�ր��A��lQ��@纼�!7��F�� �]�sZ B�62r�v�z~�K�7�c��5�.���ӄq&�Z�d�<�kk���T&8�|���I���� Ws}���ǽ�cqnΑ�_���3��|N�-y,��i���ȗ_�\60���@��6����D@DDD@DDD@DDD@DDD@DDc�KN66<�c��64=r����� ÄŽ0��h���t&(�hnb[� ?��^��\��â|�,�/h�\��R��5�? �0�!צ܉-����G����٬��Q�zA���1�����V��� �:R���`�$��ik��H����D4�����#dk����� h�}����7���w%�������*o8wG�LycuT�.���ܯ7��I��u^���)��/c�,s�Nq�ۺ�;�ך�YH2���.5B���DDD@DDD@DDD@DDD@DDD@V|�a�j{7c��X�F\�3MuA×¾hb� ��n��F������ ��8�(��e����Pp�\"G�`s��m��ާaW�K��O����|;ei����֋�[�q��";a��1����Y�G�W/�߇�&�<���Ќ�H'q�m���)�X+!���=�m�ۚ丷~6a^X�)���,�>#&6G���Y��{����"" """ """ """ """ ""��at\/�a�8 �yp%�lhl�n����)���i�t��B�������������?��modskinlienminh.com - WSOX ENC readme.txt000064400000005722146731130140006550 0ustar00=== Google Analytics for WooCommerce === Contributors: woocommerce, automattic, claudiosanches, bor0, royho, laurendavissmith001, cshultz88, mmjones, tomalec Tags: woocommerce, google analytics Requires at least: 6.2 Tested up to: 6.5 Stable tag: 2.0.6 License: GPLv3 License URI: https://www.gnu.org/licenses/gpl-3.0.html Provides integration between Google Analytics and WooCommerce. == Description == This plugin provides the integration between Google Analytics and the WooCommerce plugin. You can link a referral to a purchase and add transaction information to your Google Analytics data. It supports Global Site Tag (GA4) and eCommerce event tracking. Please visit the [documentation page for additional information](https://woo.com/document/google-analytics-integration/). Contributions are welcome via the [GitHub repository](https://github.com/woocommerce/woocommerce-google-analytics-integration). == Installation == 1. Download the plugin file to your computer and unzip it 2. Using an FTP program, or your hosting control panel, upload the unzipped plugin folder to your WordPress installation’s wp-content/plugins/ directory. 3. Activate the plugin from the Plugins menu within the WordPress admin. 4. Don't forget to enable e-commerce tracking in your Google Analytics account: [https://support.google.com/analytics/answer/1009612?hl=en](https://support.google.com/analytics/answer/1009612?hl=en) Or use the automatic installation wizard through your admin panel, just search for this plugin's name. == Frequently Asked Questions == = Where can I find the setting for this plugin? = This plugin will add the settings to the Integration tab, found in the WooCommerce → Settings menu. = I don't see the code on my site. Where is it? = We purposefully don't track admin visits to the site. Log out of the site (or open a Google Chrome Incognito window) and check if the code is there for non-admins. Also please make sure to enter your Google Analytics ID under WooCommerce → Settings → Integrations. = My code is there. Why is it still not tracking sales? = Duplicate Google Analytics code causes a conflict in tracking. Remove any other Google Analytics plugins or code from your site to avoid duplication and conflicts in tracking. == Screenshots == 1. Google Analytics Integration Settings. == Changelog == = 2.0.6 - 2024-04-09 = * Tweak - WC 8.8 compatibility. = 2.0.5 - 2024-04-04 = * Tweak - Register `woocommerce-google-analytics-integration` script earlier, so other extensions can plug in. * Update - Separate the site tag from the event tracking file and delay execution until DOMContentLoaded. = 2.0.4 - 2024-03-26 = * Dev - Add QIT workflow. * Dev - E2E tests for the All Products block. * Dev - Remove unused functions from code. * Fix - Warning after plugin install using wp-cli. * Tweak - Add WP 6.5 Require plugins header. [See changelog for all versions](https://raw.githubusercontent.com/woocommerce/woocommerce-google-analytics-integration/trunk/changelog.txt). includes/class-wc-google-analytics-task.php000064400000002657146731130140015010 0ustar00get_settings_url(); } /** * Check if the task is complete. * * @return bool */ public function is_complete() { return WC_Google_Analytics_Integration::get_integration()->is_setup_complete(); } } includes/class-wc-abstract-google-analytics-js.php000064400000025073146731130140016260 0ustar00attach_event_data(); if ( did_action( 'woocommerce_blocks_loaded' ) ) { woocommerce_store_api_register_endpoint_data( array( 'endpoint' => ProductSchema::IDENTIFIER, 'namespace' => 'woocommerce_google_analytics_integration', 'data_callback' => array( $this, 'data_callback' ), 'schema_callback' => array( $this, 'schema_callback' ), 'schema_type' => ARRAY_A, ) ); woocommerce_store_api_register_endpoint_data( array( 'endpoint' => CartItemSchema::IDENTIFIER, 'namespace' => 'woocommerce_google_analytics_integration', 'data_callback' => array( $this, 'data_callback' ), 'schema_callback' => array( $this, 'schema_callback' ), 'schema_type' => ARRAY_A, ) ); } } /** * Hook into various parts of WooCommerce and set the relevant * script data that the frontend tracking script will use. * * @return void */ public function attach_event_data(): void { add_action( 'wp_head', function () { $this->set_script_data( 'cart', $this->get_formatted_cart() ); } ); add_action( 'woocommerce_before_single_product', function () { global $product; $this->set_script_data( 'product', $this->get_formatted_product( $product ) ); } ); add_action( 'woocommerce_add_to_cart', function ( $cart_item_key, $product_id, $quantity, $variation_id, $variation ) { $this->set_script_data( 'added_to_cart', $this->get_formatted_product( wc_get_product( $product_id ), $variation_id, $variation ) ); }, 10, 5 ); add_filter( 'woocommerce_loop_add_to_cart_link', function ( $button, $product ) { $this->append_script_data( 'products', $this->get_formatted_product( $product ) ); return $button; }, 10, 2 ); add_action( 'woocommerce_thankyou', function ( $order_id ) { if ( 'yes' === self::get( 'ga_ecommerce_tracking_enabled' ) ) { $order = wc_get_order( $order_id ); if ( $order && $order->get_meta( '_ga_tracked' ) !== '1' ) { // Check order key. // phpcs:ignore WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized $order_key = empty( $_GET['key'] ) ? '' : wc_clean( wp_unslash( $_GET['key'] ) ); if ( $order->key_is_valid( $order_key ) ) { // Mark the order as tracked. $order->update_meta_data( '_ga_tracked', 1 ); $order->save(); $this->set_script_data( 'order', $this->get_formatted_order( $order ) ); } } } } ); } /** * Return one of our settings * * @param string $setting Key/name for the setting. * * @return string|null Value of the setting or null if not found */ protected static function get( $setting ): ?string { return self::$settings[ $setting ] ?? null; } /** * Generic GA snippet for opt out */ public static function load_opt_out(): void { $code = " var gaProperty = '" . esc_js( self::get( 'ga_id' ) ) . "'; var disableStr = 'ga-disable-' + gaProperty; if ( document.cookie.indexOf( disableStr + '=true' ) > -1 ) { window[disableStr] = true; } function gaOptout() { document.cookie = disableStr + '=true; expires=Thu, 31 Dec 2099 23:59:59 UTC; path=/'; window[disableStr] = true; }"; wp_register_script( 'google-analytics-opt-out', '', array(), null, false ); wp_add_inline_script( 'google-analytics-opt-out', $code ); wp_enqueue_script( 'google-analytics-opt-out' ); } /** * Get item identifier from product data * * @param WC_Product $product WC_Product Object. * * @return string */ public static function get_product_identifier( WC_Product $product ): string { $identifier = $product->is_type( 'variation' ) ? $product->get_parent_id() : $product->get_id(); if ( 'product_sku' === self::get( 'ga_product_identifier' ) ) { if ( ! empty( $product->get_sku() ) ) { $identifier = $product->get_sku(); } else { $identifier = '#' . ( $product->is_type( 'variation' ) ? $product->get_parent_id() : $product->get_id() ); } } return apply_filters( 'woocommerce_ga_product_identifier', $identifier, $product ); } /** * Returns an array of cart data in the required format * * @return array */ public function get_formatted_cart(): array { return array( 'items' => array_map( function ( $item ) { return array_merge( $this->get_formatted_product( $item['data'] ), array( 'quantity' => $item['quantity'], 'prices' => array( 'price' => $this->get_formatted_price( $item['line_total'] ), 'currency_minor_unit' => wc_get_price_decimals(), ), ) ); }, array_values( WC()->cart->get_cart() ) ), 'coupons' => WC()->cart->get_coupons(), 'totals' => array( 'currency_code' => get_woocommerce_currency(), 'total_price' => $this->get_formatted_price( WC()->cart->get_total( 'edit' ) ), 'currency_minor_unit' => wc_get_price_decimals(), ), ); } /** * Returns an array of product data in the required format * * @param WC_Product $product The product to format. * @param int $variation_id Variation product ID. * @param array|bool $variation An array containing product variation attributes to include in the product data. * For the "variation" type products, we'll use product->get_attributes. * * @return array */ public function get_formatted_product( WC_Product $product, $variation_id = 0, $variation = false ): array { $product_id = $product->is_type( 'variation' ) ? $product->get_parent_id() : $product->get_id(); $price = $product->get_price(); // Get product price from chosen variation if set. if ( $variation_id ) { $variation_product = wc_get_product( $variation_id ); if ( $variation_product ) { $price = $variation_product->get_price(); } } $formatted = array( 'id' => $product_id, 'name' => $product->get_title(), 'categories' => array_map( fn( $category ) => array( 'name' => $category->name ), wc_get_product_terms( $product_id, 'product_cat', array( 'number' => 5 ) ) ), 'prices' => array( 'price' => $this->get_formatted_price( $price ), 'currency_minor_unit' => wc_get_price_decimals(), ), 'extensions' => array( 'woocommerce_google_analytics_integration' => array( 'identifier' => $this->get_product_identifier( $product ), ), ), ); if ( $product->is_type( 'variation' ) ) { $variation = $product->get_attributes(); } if ( is_array( $variation ) ) { $formatted['variation'] = implode( ', ', array_map( function ( $attribute, $value ) { return sprintf( '%s: %s', str_replace( 'attribute_', '', $attribute ), $value ); }, array_keys( $variation ), array_values( $variation ) ) ); } return $formatted; } /** * Returns an array of order data in the required format * * @param WC_Abstract_Order $order An instance of the WooCommerce Order object. * * @return array */ public function get_formatted_order( $order ): array { return array( 'id' => $order->get_id(), 'affiliation' => get_bloginfo( 'name' ), 'totals' => array( 'currency_code' => $order->get_currency(), 'currency_minor_unit' => wc_get_price_decimals(), 'tax_total' => $this->get_formatted_price( $order->get_total_tax() ), 'shipping_total' => $this->get_formatted_price( $order->get_total_shipping() ), 'total_price' => $this->get_formatted_price( $order->get_total() ), ), 'items' => array_map( function ( $item ) { return array_merge( $this->get_formatted_product( $item->get_product() ), array( 'quantity' => $item->get_quantity(), ) ); }, array_values( $order->get_items() ), ), ); } /** * Formats a price the same way WooCommerce Blocks does * * @param mixed $value The price value for format * * @return int */ public function get_formatted_price( $value ): int { return intval( round( ( (float) wc_format_decimal( $value ) ) * ( 10 ** absint( wc_get_price_decimals() ) ), 0 ) ); } /** * Add product identifier to StoreAPI * * @param WC_Product|array $product Either an instance of WC_Product or a cart item array depending on the endpoint * * @return array */ public function data_callback( $product ): array { $product = is_a( $product, 'WC_Product' ) ? $product : $product['data']; return array( 'identifier' => (string) $this->get_product_identifier( $product ), ); } /** * Schema for the extended StoreAPI data * * @return array */ public function schema_callback(): array { return array( 'identifier' => array( 'description' => __( 'The formatted product identifier to use in Google Analytics events.', 'woocommerce-google-analytics-integration' ), 'type' => 'string', 'readonly' => true, ), ); } /** * Returns the tracker variable this integration should use * * @return string */ abstract public static function tracker_function_name(): string; /** * Add an event to the script data * * @param string $type The type of event this data is related to. * @param string|array $data The event data to add. * * @return void */ abstract public function set_script_data( string $type, $data ): void; /** * Append data to an existing script data array * * @param string $type The type of event this data is related to. * @param string|array $data The event data to add. * * @return void */ abstract public function append_script_data( string $type, $data ): void; /** * Get the class instance * * @param array $settings Settings * @return WC_Abstract_Google_Analytics_JS */ abstract public static function get_instance( $settings = array() ): WC_Abstract_Google_Analytics_JS; } includes/class-wc-google-analytics.php000064400000034223146731130140014042 0ustar00settings ); } /** * Constructor * Init and hook in the integration. */ public function __construct() { $this->id = 'google_analytics'; $this->method_title = __( 'Google Analytics', 'woocommerce-google-analytics-integration' ); $this->method_description = __( 'Google Analytics is a free service offered by Google that generates detailed statistics about the visitors to a website.', 'woocommerce-google-analytics-integration' ); // Load the settings $this->init_form_fields(); $this->init_settings(); add_action( 'admin_notices', array( $this, 'universal_analytics_upgrade_notice' ) ); include_once 'class-wc-abstract-google-analytics-js.php'; include_once 'class-wc-google-gtag-js.php'; if ( ! $this->disable_tracking( 'all' ) ) { $this->get_tracking_instance(); } // Display a task on "Things to do next section" add_action( 'init', array( $this, 'add_wc_setup_task' ), 20 ); // Admin Options add_filter( 'woocommerce_tracker_data', array( $this, 'track_settings' ) ); add_action( 'woocommerce_update_options_integration_google_analytics', array( $this, 'process_admin_options' ) ); add_action( 'woocommerce_update_options_integration_google_analytics', array( $this, 'show_options_info' ) ); add_action( 'admin_init', array( $this, 'privacy_policy' ) ); // utm_nooverride parameter for Google AdWords add_filter( 'woocommerce_get_return_url', array( $this, 'utm_nooverride' ) ); // Dequeue the WooCommerce Blocks Google Analytics integration, // not to let it register its `gtag` function so that we could provide a more detailed configuration. add_action( 'wp_enqueue_scripts', function () { wp_dequeue_script( 'wc-blocks-google-analytics' ); } ); } /** * Conditionally display an error notice to the merchant if the stored property ID starts with "UA" * * @return void */ public function universal_analytics_upgrade_notice() { if ( 'ua' === substr( strtolower( $this->get_option( 'ga_id' ) ), 0, 2 ) ) { printf( '

%2$s

', 'notice notice-error', sprintf( /* translators: 1) URL for Google documentation on upgrading from UA to GA4 2) URL to WooCommerce Google Analytics settings page */ esc_html__( 'Your website is configured to use Universal Analytics which Google retired in July of 2023. Update your account using the %1$ssetup assistant%2$s and then update your %3$sWooCommerce settings%4$s.', 'woocommerce-google-analytics-integration' ), '', '', '', '' ) ); } } /** * Tells WooCommerce which settings to display under the "integration" tab */ public function init_form_fields() { $this->form_fields = array( 'ga_product_identifier' => array( 'title' => __( 'Product Identification', 'woocommerce-google-analytics-integration' ), 'description' => __( 'Specify how your products will be identified to Google Analytics. Changing this setting may cause issues with historical data if a product was previously identified using a different structure.', 'woocommerce-google-analytics-integration' ), 'type' => 'select', 'options' => array( 'product_id' => __( 'Product ID', 'woocommerce-google-analytics-integration' ), 'product_sku' => __( 'Product SKU with prefixed (#) ID as fallback', 'woocommerce-google-analytics-integration' ), ), // If the option is not set then the product SKU is used as default for existing installations 'default' => 'product_sku', ), 'ga_id' => array( 'title' => __( 'Google Analytics Tracking ID', 'woocommerce-google-analytics-integration' ), 'description' => __( 'Log into your Google Analytics account to find your ID. e.g. GT-XXXXX or G-XXXXX', 'woocommerce-google-analytics-integration' ), 'type' => 'text', 'placeholder' => 'GT-XXXXX', 'default' => get_option( 'woocommerce_ga_id' ), // Backwards compat ), 'ga_support_display_advertising' => array( 'label' => __( '"Display Advertising" Support', 'woocommerce-google-analytics-integration' ), /* translators: Read more link */ 'description' => sprintf( __( 'Set the Google Analytics code to support Display Advertising. %1$sRead more about Display Advertising%2$s.', 'woocommerce-google-analytics-integration' ), '', '' ), 'type' => 'checkbox', 'checkboxgroup' => '', 'default' => get_option( 'woocommerce_ga_support_display_advertising' ) ? get_option( 'woocommerce_ga_support_display_advertising' ) : 'yes', // Backwards compat ), 'ga_404_tracking_enabled' => array( 'label' => __( 'Track 404 (Not found) Errors', 'woocommerce-google-analytics-integration' ), /* translators: Read more link */ 'description' => sprintf( __( 'Enable this to find broken or dead links. An "Event" with category "Error" and action "404 Not Found" will be created in Google Analytics for each incoming pageview to a non-existing page. By setting up a "Custom Goal" for these events within Google Analytics you can find out where broken links originated from (the referrer). %1$sRead how to set up a goal%2$s.', 'woocommerce-google-analytics-integration' ), '', '' ), 'type' => 'checkbox', 'checkboxgroup' => '', 'default' => 'yes', ), 'ga_linker_allow_incoming_enabled' => array( 'label' => __( 'Accept Incoming Linker Parameters', 'woocommerce-google-analytics-integration' ), 'description' => __( 'Enabling this option will allow incoming linker parameters from other websites.', 'woocommerce-google-analytics-integration' ), 'type' => 'checkbox', 'checkboxgroup' => '', 'default' => 'no', ), 'ga_ecommerce_tracking_enabled' => array( 'title' => __( 'Event Tracking', 'woocommerce-google-analytics-integration' ), 'label' => __( 'Purchase Transactions', 'woocommerce-google-analytics-integration' ), 'description' => __( 'This requires a payment gateway that redirects to the thank you/order received page after payment. Orders paid with gateways which do not do this will not be tracked.', 'woocommerce-google-analytics-integration' ), 'type' => 'checkbox', 'checkboxgroup' => 'start', 'default' => get_option( 'woocommerce_ga_ecommerce_tracking_enabled' ) ? get_option( 'woocommerce_ga_ecommerce_tracking_enabled' ) : 'yes', // Backwards compat ), 'ga_event_tracking_enabled' => array( 'label' => __( 'Add to Cart Events', 'woocommerce-google-analytics-integration' ), 'type' => 'checkbox', 'checkboxgroup' => '', 'default' => 'yes', ), 'ga_enhanced_remove_from_cart_enabled' => array( 'label' => __( 'Remove from Cart Events', 'woocommerce-google-analytics-integration' ), 'type' => 'checkbox', 'checkboxgroup' => '', 'default' => 'yes', ), 'ga_enhanced_product_impression_enabled' => array( 'label' => __( 'Product Impressions from Listing Pages', 'woocommerce-google-analytics-integration' ), 'type' => 'checkbox', 'checkboxgroup' => '', 'default' => 'yes', ), 'ga_enhanced_product_click_enabled' => array( 'label' => __( 'Product Clicks from Listing Pages', 'woocommerce-google-analytics-integration' ), 'type' => 'checkbox', 'checkboxgroup' => '', 'default' => 'yes', ), 'ga_enhanced_product_detail_view_enabled' => array( 'label' => __( 'Product Detail Views', 'woocommerce-google-analytics-integration' ), 'type' => 'checkbox', 'checkboxgroup' => '', 'default' => 'yes', ), 'ga_enhanced_checkout_process_enabled' => array( 'label' => __( 'Checkout Process Initiated', 'woocommerce-google-analytics-integration' ), 'type' => 'checkbox', 'checkboxgroup' => '', 'default' => 'yes', ), 'ga_linker_cross_domains' => array( 'title' => __( 'Cross Domain Tracking', 'woocommerce-google-analytics-integration' ), /* translators: Read more link */ 'description' => sprintf( __( 'Add a comma separated list of domains for automatic linking. %1$sRead more about Cross Domain Measurement%2$s', 'woocommerce-google-analytics-integration' ), '', '' ), 'type' => 'text', 'placeholder' => 'example.com, example.net', 'default' => '', ), ); } /** * Shows some additional help text after saving the Google Analytics settings */ public function show_options_info() { $this->method_description .= "

" . __( 'Please allow Google Analytics 24 hours to start displaying results.', 'woocommerce-google-analytics-integration' ) . '

'; // phpcs:disable WordPress.Security.NonceVerification.Recommended if ( isset( $_REQUEST['woocommerce_google_analytics_ga_ecommerce_tracking_enabled'] ) && true === (bool) $_REQUEST['woocommerce_google_analytics_ga_ecommerce_tracking_enabled'] ) { $this->method_description .= "

" . __( 'Please note, for transaction tracking to work properly, you will need to use a payment gateway that redirects the customer back to a WooCommerce order received/thank you page.', 'woocommerce-google-analytics-integration' ) . '

'; } } /** * Hooks into woocommerce_tracker_data and tracks some of the analytic settings (just enabled|disabled status) * only if you have opted into WooCommerce tracking * https://woo.com/usage-tracking/ * * @param array $data Current WC tracker data. * @return array Updated WC Tracker data. */ public function track_settings( $data ) { $settings = $this->settings; $data['wc-google-analytics'] = array( 'support_display_advertising' => $settings['ga_support_display_advertising'], 'ga_404_tracking_enabled' => $settings['ga_404_tracking_enabled'], 'ecommerce_tracking_enabled' => $settings['ga_ecommerce_tracking_enabled'], 'event_tracking_enabled' => $settings['ga_event_tracking_enabled'], 'plugin_version' => WC_GOOGLE_ANALYTICS_INTEGRATION_VERSION, 'linker_allow_incoming_enabled' => empty( $settings['ga_linker_allow_incoming_enabled'] ) ? 'no' : 'yes', 'linker_cross_domains' => $settings['ga_linker_cross_domains'], ); // ID prefix, blank, or X for unknown $prefix = strstr( strtoupper( $settings['ga_id'] ), '-', true ); if ( in_array( $prefix, array( 'UA', 'G', 'GT' ), true ) || empty( $prefix ) ) { $data['wc-google-analytics']['ga_id'] = $prefix; } else { $data['wc-google-analytics']['ga_id'] = 'X'; } return $data; } /** * Add suggested privacy policy content * * @return void */ public function privacy_policy() { $policy_text = sprintf( /* translators: 1) HTML anchor open tag 2) HTML anchor closing tag */ esc_html__( 'By using this extension, you may be storing personal data or sharing data with an external service. %1$sLearn more about what data is collected by Google and what you may want to include in your privacy policy%2$s.', 'woocommerce-google-analytics-integration' ), '', '' ); // As the extension doesn't offer suggested privacy policy text, the button to copy it is hidden. $content = '

' . $policy_text . '

'; wp_add_privacy_policy_content( 'Google Analytics for WooCommerce', wpautop( $content, false ) ); } /** * Check if tracking is disabled * * @param string $type The setting to check * @return bool True if tracking for a certain setting is disabled */ private function disable_tracking( $type ) { return is_admin() || current_user_can( 'manage_options' ) || empty( $this->settings['ga_id'] ) || 'no' === $type || apply_filters( 'woocommerce_ga_disable_tracking', false, $type ); } /** * Add the utm_nooverride parameter to any return urls. This makes sure Google Adwords doesn't mistake the offsite gateway as the referrer. * * @param string $return_url WooCommerce Return URL * @return string URL */ public function utm_nooverride( $return_url ) { // We don't know if the URL already has the parameter so we should remove it just in case $return_url = remove_query_arg( 'utm_nooverride', $return_url ); // Now add the utm_nooverride query arg to the URL $return_url = add_query_arg( 'utm_nooverride', '1', $return_url ); return esc_url( $return_url, null, 'db' ); } /** * Check if the Google Analytics Tracking ID has been set up. * * @since 1.5.17 * * @return bool Whether the Google Analytics setup is completed. */ public function is_setup_complete() { return (bool) $this->get_option( 'ga_id' ); } /** * Adds the setup task to the Tasklists. * * @since 1.5.17 */ public function add_wc_setup_task() { require_once 'class-wc-google-analytics-task.php'; TaskLists::add_task( 'extended', new WC_Google_Analytics_Task( TaskLists::get_list( 'extended' ) ) ); } } includes/class-wc-google-gtag-js.php000064400000023002146731130140013400 0ustar00 array( 'begin_checkout' => 'woocommerce_before_checkout_form', 'purchase' => 'woocommerce_thankyou', 'add_to_cart' => 'woocommerce_add_to_cart', 'remove_from_cart' => 'woocommerce_cart_item_removed', 'view_item' => 'woocommerce_after_single_product', ), 'filters' => array( 'view_item_list' => 'woocommerce_loop_add_to_cart_link', ), ); /** * Constructor * Takes our settings from the parent class so we can later use them in the JS snippets * * @param array $settings Settings */ public function __construct( $settings = array() ) { parent::__construct(); self::$settings = $settings; $this->map_hooks(); $this->register_scripts(); // Setup frontend scripts add_action( 'wp_enqueue_scripts', array( $this, 'enquque_tracker' ), 5 ); add_action( 'wp_footer', array( $this, 'inline_script_data' ) ); } /** * Register manager and tracker scripts. * Call early so other extensions could add inline date to it. * * @return void */ private function register_scripts(): void { wp_register_script( 'google-tag-manager', 'https://www.googletagmanager.com/gtag/js?id=' . self::get( 'ga_id' ), array(), null, array( 'strategy' => 'async', ) ); wp_register_script( $this->gtag_script_handle, '', array(), null, array( 'in_footer' => false, ) ); wp_add_inline_script( $this->gtag_script_handle, apply_filters( 'woocommerce_gtag_snippet', sprintf( '/* Google Analytics for WooCommerce (gtag.js) */ window.dataLayer = window.dataLayer || []; function %2$s(){dataLayer.push(arguments);} // Set up default consent state. for ( const mode of %4$s || [] ) { %2$s( "consent", "default", mode ); } %2$s("js", new Date()); %2$s("set", "developer_id.%3$s", true); %2$s("config", "%1$s", %5$s);', esc_js( $this->get( 'ga_id' ) ), esc_js( $this->tracker_function_name() ), esc_js( static::DEVELOPER_ID ), json_encode( $this->get_consent_modes() ), json_encode( $this->get_site_tag_config() ) ) ) ); wp_enqueue_script( $this->gtag_script_handle ); wp_register_script( $this->script_handle, Plugin::get_instance()->get_js_asset_url( 'main.js' ), array( ...Plugin::get_instance()->get_js_asset_dependencies( 'main' ), 'google-tag-manager', ), Plugin::get_instance()->get_js_asset_version( 'main' ), true ); } /** * Enqueue tracker scripts and its inline config. * We need to execute tracker.js w/ `gtag` configuration before any trackable action may happen. * * @return void */ public function enquque_tracker(): void { wp_enqueue_script( 'google-tag-manager' ); // tracker.js needs to be executed ASAP, the remaining bits for main.js could be deffered, // but to reduce the traffic, we ship it all together. wp_enqueue_script( $this->script_handle ); } /** * Add all event data via an inline script in the footer to ensure all the data is collected in time. * * @return void */ public function inline_script_data(): void { wp_register_script( $this->data_script_handle, '', array( $this->script_handle ), null, array( 'in_footer' => true, ) ); wp_add_inline_script( $this->data_script_handle, sprintf( 'window.ga4w = { data: %1$s, settings: %2$s }; document.dispatchEvent(new Event("ga4w:ready"));', $this->get_script_data(), wp_json_encode( array( 'tracker_function_name' => $this->tracker_function_name(), 'events' => $this->get_enabled_events(), 'identifier' => $this->get( 'ga_product_identifier' ), ), ), ) ); wp_enqueue_script( $this->data_script_handle ); } /** * Hook into WooCommerce and add corresponding Blocks Actions to our event data * * @return void */ public function map_hooks(): void { array_walk( $this->mappings['actions'], function ( $hook, $gtag_event ) { add_action( $hook, function () use ( $gtag_event ) { $this->append_event( $gtag_event ); } ); } ); array_walk( $this->mappings['filters'], function ( $hook, $gtag_event ) { add_action( $hook, function ( $filtered_value ) use ( $gtag_event ) { $this->append_event( $gtag_event ); return $filtered_value; } ); } ); } /** * Appends a specific event, if it's not included yet. * * @param string $gtag_event * @return void */ private function append_event( string $gtag_event ) { if ( ! in_array( $gtag_event, $this->script_data['events'] ?? [], true ) ) { $this->append_script_data( 'events', $gtag_event ); } } /** * Set script data for a specific event * * @param string $type The type of event this data is related to. * @param string|array $data The event data to add. * * @return void */ public function set_script_data( string $type, $data ): void { $this->script_data[ $type ] = $data; } /** * Append data to an existing script data array * * @param string $type The type of event this data is related to. * @param string|array $data The event data to add. * * @return void */ public function append_script_data( string $type, $data ): void { if ( ! isset( $this->script_data[ $type ] ) ) { $this->script_data[ $type ] = array(); } $this->script_data[ $type ][] = $data; } /** * Return a JSON encoded string of all script data for the current page load * * @return string */ public function get_script_data(): string { return wp_json_encode( $this->script_data ); } /** * Returns the tracker variable this integration should use * * @return string */ public static function tracker_function_name(): string { return apply_filters( 'woocommerce_gtag_tracker_variable', 'gtag' ); } /** * Return Google Analytics configuration, for JS to read. * * @return array */ public function get_site_tag_config(): array { return apply_filters( 'woocommerce_ga_gtag_config', array( 'track_404' => 'yes' === $this->get( 'ga_404_tracking_enabled' ), 'allow_google_signals' => 'yes' === $this->get( 'ga_support_display_advertising' ), 'logged_in' => is_user_logged_in(), 'linker' => array( 'domains' => ! empty( $this->get( 'ga_linker_cross_domains' ) ) ? array_map( 'esc_js', explode( ',', $this->get( 'ga_linker_cross_domains' ) ) ) : array(), 'allow_incoming' => 'yes' === $this->get( 'ga_linker_allow_incoming_enabled' ), ), 'custom_map' => array( 'dimension1' => 'logged_in', ), ), ); } /** * Get an array containing the names of all enabled events * * @return array */ public static function get_enabled_events(): array { $events = array(); $settings = array( 'purchase' => 'ga_ecommerce_tracking_enabled', 'add_to_cart' => 'ga_event_tracking_enabled', 'remove_from_cart' => 'ga_enhanced_remove_from_cart_enabled', 'view_item_list' => 'ga_enhanced_product_impression_enabled', 'select_content' => 'ga_enhanced_product_click_enabled', 'view_item' => 'ga_enhanced_product_detail_view_enabled', 'begin_checkout' => 'ga_enhanced_checkout_process_enabled', ); foreach ( $settings as $event => $setting_name ) { if ( 'yes' === self::get( $setting_name ) ) { $events[] = $event; } } return $events; } /** * Get the default state configuration of consent mode. */ protected static function get_consent_modes(): array { $consent_modes = array( array( 'analytics_storage' => 'denied', 'ad_storage' => 'denied', 'ad_user_data' => 'denied', 'ad_personalization' => 'denied', 'region' => array( 'AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE', 'GR', 'HU', 'IS', 'IE', 'IT', 'LV', 'LI', 'LT', 'LU', 'MT', 'NL', 'NO', 'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE', 'GB', 'CH', ), ), ); /** * Filters the default gtag consent mode configuration. * * @param array $consent_modes Array of default state configuration of consent mode. */ return apply_filters( 'woocommerce_ga_gtag_consent_modes', $consent_modes ); } /** * Get the class instance * * @param array $settings Settings * @return WC_Abstract_Google_Analytics_JS */ public static function get_instance( $settings = array() ): WC_Abstract_Google_Analytics_JS { if ( null === self::$instance ) { self::$instance = new self( $settings ); } return self::$instance; } } woocommerce-google-analytics-integration.php000064400000025402146731130140015357 0ustar00maybe_show_ga_pro_notices(); WC_Google_Analytics_Integration::get_instance()->maybe_set_defaults(); } ); // HPOS compatibility declaration. add_action( 'before_woocommerce_init', function () { if ( class_exists( FeaturesUtil::class ) ) { FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__ ); FeaturesUtil::declare_compatibility( 'cart_checkout_blocks', __FILE__ ); FeaturesUtil::declare_compatibility( 'product_block_editor', __FILE__ ); } } ); /** * Google Analytics for WooCommerce main class. */ class WC_Google_Analytics_Integration { /** @var WC_Google_Analytics_Integration $instance Instance of this class. */ protected static $instance = null; /** * Initialize the plugin. */ public function __construct() { if ( ! class_exists( 'WooCommerce' ) ) { add_action( 'admin_notices', [ $this, 'woocommerce_missing_notice' ] ); return; } // Load plugin text domain add_action( 'init', array( $this, 'load_plugin_textdomain' ) ); // Track completed orders and determine whether the GA Pro notice should be displayed. add_action( 'woocommerce_order_status_completed', array( $this, 'maybe_show_ga_pro_notices' ) ); // Checks which WooCommerce is installed. if ( class_exists( 'WC_Integration' ) && defined( 'WOOCOMMERCE_VERSION' ) && version_compare( WOOCOMMERCE_VERSION, WC_GOOGLE_ANALYTICS_INTEGRATION_MIN_WC_VER, '>=' ) ) { include_once 'includes/class-wc-google-analytics.php'; // Register the integration. add_filter( 'woocommerce_integrations', array( $this, 'add_integration' ) ); } else { add_action( 'admin_notices', array( $this, 'woocommerce_missing_notice' ) ); } add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'plugin_links' ) ); } /** * Gets the settings page URL. * * @since 1.5.17 * * @return string Settings URL */ public function get_settings_url() { return add_query_arg( array( 'page' => 'wc-settings', 'tab' => 'integration', 'section' => 'google_analytics', ), admin_url( 'admin.php' ) ); } /** * Add links on the plugins page (Settings & Support) * * @param array $links Default links * @return array Default + added links */ public function plugin_links( $links ) { $settings_url = $this->get_settings_url(); $support_url = 'https://wordpress.org/support/plugin/woocommerce-google-analytics-integration'; $docs_url = 'https://woo.com/document/google-analytics-integration/?utm_source=wordpress&utm_medium=all-plugins-page&utm_campaign=doc-link&utm_content=woocommerce-google-analytics-integration'; $plugin_links = array( '' . esc_html__( 'Settings', 'woocommerce-google-analytics-integration' ) . '', '' . esc_html__( 'Support', 'woocommerce-google-analytics-integration' ) . '', '' . esc_html__( 'Documentation', 'woocommerce-google-analytics-integration' ) . '', ); return array_merge( $plugin_links, $links ); } /** * Return an instance of this class. * * @return WC_Google_Analytics_Integration A single instance of this class. */ public static function get_instance() { // If the single instance hasn't been set, set it now. if ( null === self::$instance ) { self::$instance = new self(); } return self::$instance; } /** * Load the plugin text domain for translation. */ public function load_plugin_textdomain() { $locale = apply_filters( 'plugin_locale', get_locale(), 'woocommerce-google-analytics-integration' ); load_textdomain( 'woocommerce-google-analytics-integration', trailingslashit( WP_LANG_DIR ) . 'woocommerce-google-analytics-integration/woocommerce-google-analytics-integration-' . $locale . '.mo' ); load_plugin_textdomain( 'woocommerce-google-analytics-integration', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' ); } /** * WooCommerce fallback notice. */ public function woocommerce_missing_notice() { if ( defined( 'WOOCOMMERCE_VERSION' ) ) { /* translators: 1 is the required component, 2 the Woocommerce version */ $error = sprintf( __( 'Google Analytics for WooCommerce requires WooCommerce version %1$s or higher. You are using version %2$s', 'woocommerce-google-analytics-integration' ), WC_GOOGLE_ANALYTICS_INTEGRATION_MIN_WC_VER, WOOCOMMERCE_VERSION ); } else { /* translators: 1 is the required component */ $error = sprintf( __( 'Google Analytics for WooCommerce requires WooCommerce version %1$s or higher.', 'woocommerce-google-analytics-integration' ), WC_GOOGLE_ANALYTICS_INTEGRATION_MIN_WC_VER ); } echo '

' . wp_kses_post( $error ) . '

'; } /** * Add a new integration to WooCommerce. * * @param array $integrations WooCommerce integrations. * @return array Google Analytics for WooCommerce added. */ public function add_integration( $integrations ) { $integrations[] = 'WC_Google_Analytics'; return $integrations; } /** * Get Google Analytics Integration * * @since 1.5.17 * * @return WC_Google_Analytics The Google Analytics integration. */ public static function get_integration() { return \WooCommerce::instance()->integrations->get_integration( 'google_analytics' ); } /** * Logic for Google Analytics Pro notices. */ public function maybe_show_ga_pro_notices() { // Notice was already shown if ( ! class_exists( 'WooCommerce' ) || get_option( 'woocommerce_google_analytics_pro_notice_shown', false ) ) { return; } $completed_orders = wc_orders_count( 'completed' ); // Only show the notice if there are 10 <= completed orders <= 100. if ( $completed_orders < 10 || $completed_orders > 100 ) { update_option( 'woocommerce_google_analytics_pro_notice_shown', true ); return; } $notice_html = '' . esc_html__( 'Get detailed insights into your sales with Google Analytics Pro', 'woocommerce-google-analytics-integration' ) . '

'; /* translators: 1: href link to GA pro */ $notice_html .= sprintf( __( 'Add advanced tracking for your sales funnel, coupons and more. [Learn more >]', 'woocommerce-google-analytics-integration' ), 'https://woo.com/products/woocommerce-google-analytics-pro/?utm_source=woocommerce-google-analytics-integration&utm_medium=product&utm_campaign=google%20analytics%20free%20to%20pro%20extension%20upsell' ); WC_Admin_Notices::add_custom_notice( 'woocommerce_google_analytics_pro_notice', $notice_html ); update_option( 'woocommerce_google_analytics_pro_notice_shown', true ); } /** * Set default options during activation if no settings exist * * @since 2.0.0 * * @return void */ public function maybe_set_defaults() { $settings_key = 'woocommerce_google_analytics_settings'; if ( false === get_option( $settings_key, false ) ) { update_option( $settings_key, array( 'ga_product_identifier' => 'product_id', ) ); } } /** * Get the path to something in the plugin dir. * * @param string $end End of the path. * @return string */ public function path( $end = '' ) { return untrailingslashit( __DIR__ ) . $end; } /** * Get the URL to something in the plugin dir. * * @param string $end End of the URL. * * @return string */ public function url( $end = '' ) { return untrailingslashit( plugin_dir_url( plugin_basename( __FILE__ ) ) ) . $end; } /** * Get the URL to something in the plugin JS assets build dir. * * @param string $end End of the URL. * * @return string */ public function get_js_asset_url( $end = '' ) { return $this->url( '/assets/js/build/' . $end ); } /** * Get the path to something in the plugin JS assets build dir. * * @param string $end End of the path. * @return string */ public function get_js_asset_path( $end = '' ) { return $this->path( '/assets/js/build/' . $end ); } /** * Gets the asset.php generated file for an asset name. * * @param string $asset_name The name of the asset to get the file from. * @return array The asset file. Or an empty array if the file doesn't exist. */ public function get_js_asset_file( $asset_name ) { try { // Exclusion reason: No reaching any user input // nosemgrep audit.php.lang.security.file.inclusion-arg return require $this->get_js_asset_path( $asset_name . '.asset.php' ); } catch ( Exception $e ) { return []; } } /** * Gets the dependencies for an assets based on its asset.php generated file. * * @param string $asset_name The name of the asset to get the dependencies from. * @param array $extra_dependencies Array containing extra dependencies to include in the dependency array. * * @return array The dependencies array. Empty array if no dependencies. */ public function get_js_asset_dependencies( $asset_name, $extra_dependencies = array() ) { $script_assets = $this->get_js_asset_file( $asset_name ); $dependencies = $script_assets['dependencies'] ?? []; return array_unique( array_merge( $dependencies, $extra_dependencies ) ); } /** * Gets the version for an assets based on its asset.php generated file. * * @param string $asset_name The name of the asset to get the version from. * @return string|false The version. False in case no version is found. */ public function get_js_asset_version( $asset_name ) { $script_assets = $this->get_js_asset_file( $asset_name ); return $script_assets['version'] ?? false; } } add_action( 'plugins_loaded', array( 'WC_Google_Analytics_Integration', 'get_instance' ), 0 ); } assets/js/build/main.js000064400000013552146731130140011051 0ustar00(()=>{"use strict";var t={d:(e,o)=>{for(var c in o)t.o(o,c)&&!t.o(e,c)&&Object.defineProperty(e,c,{enumerable:!0,get:o[c]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{add_to_cart:()=>g,begin_checkout:()=>y,purchase:()=>h,remove_from_cart:()=>w,search:()=>f,select_content:()=>v,view_item:()=>b,view_item_list:()=>p});const o=window.wp.i18n,c=window.wp.hooks,r=(t,e)=>{var o;const c={};return t.variation&&(c.item_variant=t.variation),{item_id:d(t),item_name:t.name,...u(t),quantity:null!==(o=t.quantity)&&void 0!==o?o:e,price:i(t.prices.price,t.prices.currency_minor_unit),...c}},n=(t,e)=>({item_id:d(t),item_name:t.name,item_list_name:e,...u(t),price:i(t.prices.price,t.prices.currency_minor_unit)}),i=(t,e=2)=>parseInt(t,10)/10**e,a=(t,e,o)=>{(0,c.removeAction)(t,e),(0,c.addAction)(t,e,o)},d=t=>{const e=t.extensions?.woocommerce_google_analytics_integration?.identifier;return void 0!==e?e:"product_sku"===window.ga4w?.settings?.identifier?t.sku?t.sku:"#"+t.id:t.id},s=t=>t.coupons[0]?.code?{coupon:t.coupons[0]?.code}:{},u=t=>"categories"in t&&t.categories.length?m(t.categories):{},m=t=>Object.fromEntries(t.slice(0,5).map(((t,e)=>[l(e),t.name]))),l=t=>"item_category"+(t>0?t+1:""),_=(t,e,o)=>{var c;return null!==(c=o?.items?.find((({id:e})=>e===t)))&&void 0!==c?c:e?.find((({id:e})=>e===t))},p=({products:t,listName:e=(0,o.__)("Product List","woocommerce-google-analytics-integration")})=>0!==t.length&&{item_list_id:"engagement",item_list_name:(0,o.__)("Viewing products","woocommerce-google-analytics-integration"),items:t.map(((t,o)=>({...n(t,e),index:o+1})))},g=({product:t,quantity:e=1})=>({items:t?[r(t,e)]:[]}),w=({product:t,quantity:e=1})=>({items:t?[r(t,e)]:[]}),y=({storeCart:t})=>({currency:t.totals.currency_code,value:i(t.totals.total_price,t.totals.currency_minor_unit),...s(t),items:t.items.map(r)}),v=({product:t})=>!!t&&{content_type:"product",content_id:d(t)},f=({searchTerm:t})=>({search_term:t}),b=({product:t,listName:e=(0,o.__)("Product List","woocommerce-google-analytics-integration")})=>!!t&&{items:[n(t,e)]},h=({order:t})=>void 0!==t&&{transaction_id:t.id,affiliation:t.affiliation,currency:t.totals.currency_code,value:i(t.totals.total_price,t.totals.currency_minor_unit),tax:i(t.totals.tax_total,t.totals.currency_minor_unit),shipping:i(t.totals.shipping_total,t.totals.currency_minor_unit),items:t.items.map(r)},k="woocommerce-google-analytics",A="experimental__woocommerce_blocks";function $(){const t=function({events:t,tracker_function_name:o}){return function(c){const r=e[c];if("function"!=typeof r)throw new Error(`Event ${c} is not supported.`);return function(e){const n=r(e);t.includes(c)&&n&&window[o]("event",c,n)}}}(window.ga4w.settings);!function(t,{events:e,cart:o,products:c,product:r,added_to_cart:n,order:i}){Object.values(null!=e?e:{}).forEach((e=>{"add_to_cart"===e?t(e)({product:n}):t(e)({storeCart:o,products:c,product:r,order:i})})),document.body.onadded_to_cart=(e,n,i,a)=>{const d=parseInt(a[0].dataset.product_id||a[0].value),s=r?.id===d?r:_(parseInt(d),c,o);s&&t("add_to_cart")({product:s})};const a=()=>{document.querySelectorAll(".woocommerce-cart-form .woocommerce-cart-form__cart-item .remove[data-product_id]").forEach((t=>t.addEventListener("click",d)))};function d(e){t("remove_from_cart")({product:_(parseInt(e.target.dataset.product_id),c,o)})}a();const s=document.body.onupdated_wc_div;document.body.onupdated_wc_div=(...t)=>{"function"==typeof s&&s(...t),a()};const u=document.body.onremoved_from_cart;document.body.onremoved_from_cart=(...t)=>{"function"==typeof u&&u(...t),d({target:t[3][0]})},document.querySelectorAll(".products .product:not(.wp-block-post)")?.forEach((e=>{const r=e.querySelector("a[data-product_id]")?.getAttribute("data-product_id");r&&e.addEventListener("click",(e=>{const n=e.target.closest(".woocommerce-loop-product__link"),i=e.target.classList.contains("button")&&e.target.hasAttribute("data-product_id"),a=e.target.classList.contains("add_to_cart_button")&&!e.target.classList.contains("product_type_variable");(n||i&&!a)&&t("select_content")({product:_(parseInt(r),c,o)})}))})),document.querySelectorAll(".products-block-post-template .product, .wc-block-product-template .product")?.forEach((e=>{const r=e.querySelector("[data-product_id]")?.getAttribute("data-product_id");r&&e.addEventListener("click",(e=>{const n=e.target,i=n.closest(".wc-block-components-product-image a"),a=n.closest(".wp-block-post-title a"),d=n.closest(".wc-block-components-product-button [data-product_id]");d&&d.classList.contains("add_to_cart_button")&&!d.classList.contains("product_type_variable")?t("add_to_cart")({product:_(parseInt(r),c,o)}):(i||d||a)&&t("select_content")({product:_(parseInt(r),c,o)})}))}))}(t,window.ga4w.data),(t=>{a(`${A}-product-render`,k,t("view_item")),a(`${A}-cart-remove-item`,k,t("remove_from_cart")),a(`${A}-checkout-render-checkout-form`,k,t("begin_checkout")),a(`${A}-cart-add-item`,k,(({product:e})=>{t("add_to_cart")({product:e})})),a(`${A}-product-list-render`,k,t("view_item_list")),a(`${A}-product-view-link`,k,t("select_content"))})(t)}function E(){window.ga4w||console.warn("Google Analytics for WooCommerce: Configuration and tracking data not found after the page was fully loaded. Make sure the `woocommerce-google-analytics-integration-data` script gets eventually loaded.")}(0,c.removeAction)(`${A}-checkout-submit`,k),(0,c.removeAction)(`${A}-checkout-set-email-address`,k),(0,c.removeAction)(`${A}-checkout-set-phone-number`,k),(0,c.removeAction)(`${A}-checkout-set-billing-address`,k),(0,c.removeAction)(`${A}-cart-set-item-quantity`,k),(0,c.removeAction)(`${A}-product-search`,k),(0,c.removeAction)(`${A}-store-notice-create`,k),window.ga4w?$():(document.addEventListener("ga4w:ready",$),"complete"===document.readyState?E():window.addEventListener("load",E))})();assets/js/build/main.asset.php000064400000000151146731130140012331 0ustar00 array('wp-hooks', 'wp-i18n'), 'version' => 'c4a77335eae7e6132482'); changelog.txt000064400000027135146731130140007244 0ustar00*** Changelog *** = 2.0.6 - 2024-04-09 = * Tweak - WC 8.8 compatibility. = 2.0.5 - 2024-04-04 = * Tweak - Register `woocommerce-google-analytics-integration` script earlier, so other extensions can plug in. * Update - Separate the site tag from the event tracking file and delay execution until DOMContentLoaded. = 2.0.4 - 2024-03-26 = * Dev - Add QIT workflow. * Dev - E2E tests for the All Products block. * Dev - Remove unused functions from code. * Fix - Warning after plugin install using wp-cli. * Tweak - Add WP 6.5 Require plugins header. = 2.0.3 - 2024-03-13 = * Tweak - WC 8.7 compatibility. * Tweak - WP 6.5 compatibility. = 2.0.2 - 2024-03-12 = * Dev - Add E2E testing to track events across all page types. * Fix - Add to cart & select content events for All Products Block. * Fix - Get correct variation data when formatting product. * Fix - Handle AJAX add to cart for simple products. * Fix - Purchase price format. * Fix - Track purchase transaction ID. * Fix - Typo with undefined variable. = 2.0.1 - 2024-03-07 = * Fix - Adding variable product attributes. * Fix - Resolve Google Analytics not loading if gtag already exists on the window object. * Tweak - Update Contributors list. * Tweak - Update assets and readme for 2.0. = 2.0.0 - 2024-03-05 = * Add - Basic consent mode support. * Add - Setting to specify the structure of the product identifier. * Add - Update notice for merchants using a Universal Analytics Property ID. * Dev - Remove options remapping, use settings directly. * Fix - Prevent tracking orders multiple times and additional fixes. * Remove - Universal Analytics code. * Remove - Universal Analytics integration. * Simplify tracker event handler API. * Update - Add shared tracking functionality for WooCommerce Blocks and classic pages. * Update - Extension branding to Google Analytics for WooCommerce. * Update - Tracking for GA4 when using Blocks. = 1.8.14 - 2024-02-07 = * Tweak - Declare feature compatibility for the new product editor (also called product block editor). * Tweak - WC 8.6 compatibility. = 1.8.13 - 2024-01-09 = * Dev - Upgrade all NPM dev dependencies. * Dev - Upgrade to Node.js 18. * Tweak - WC 8.5 compatibility. = 1.8.12 - 2023-12-28 = * Fix - Avoid JavaScript exceptions when sending checkout event tracking due to incompatible data structure. * Fix - Correct misplaced each product index value as its quantity when sending checkout event tracking. = 1.8.11 - 2023-12-18 = * Dev - Prevent DB warnings in unit tests. * Tweak - WC 8.4 compatibility. = 1.8.10 - 2023-11-28 = * Dev - Update phpunit polyfills to 1.1 for WP 6.4. * Fix - Add semicolon after `gtag` calls. * Fix - Prevent firing up the add_to_cart event when clicking in product image. * Tweak - Test environment setup to resolve notice. = 1.8.9 - 2023-11-07 = * Tweak - WC 8.3 compatibility. * Tweak - WP 6.4 compatibility. * Update - Use new Woo.com domain. * Update - WordPressCS to version 3.0. = 1.8.8 - 2023-10-24 = * Tweak - Declare cart_checkout_blocks feature compatibility. = 1.8.7 - 2023-10-10 = * Fix - JS syntax error on pages with cart and mini-cart rendered, which was causing purchases and cart removals not to be tracked. = 1.8.6 - 2023-10-03 = * Add - Privacy policy guide section. * Dev - Enable since tag replacement. * Fix - Track select_content instead of add_to_cart for variations. * Tweak - Add documentation link with UTM parameters. * Tweak - Tracking for Products ( Add To Cart and Impression) when using Products (Beta) Block. * Tweak - WC 8.2 compatibility. = 1.8.5 - 2023-09-14 = * Dev - Add Workflow for generation Hooks documentation. * Dev - Fetch WooCommerce and WordPress versions for our tests. * Fix - Add To Cart and Impression events when using Blocks. * Fix - Compat - Add PHP 8.2 support. * Tweak - WC 8.1.0 compatibility. = 1.8.4 - 2023-08-08 = * Dev - Add release preparation GH workflow. * Fix - Add async attribute in `google-tag-manager` script. * Tweak - WC 8.0 compatibility. * Tweak - WP 6.3 compatibility. = 1.8.3 - 2023-07-11 = * Dev - Set engines for the repository. * Fix - Record consecutive cart removals. * Tweak - WC 7.9 compatibility. = 1.8.2 - 2023-06-13 = * Tweak - WC 7.8 compatibility. = 1.8.1 - 2023-05-09 = * Fix - Fatal error when running with Elementor. * Tweak - WC 7.7 compatibility. = 1.8.0 - 2023-05-02 = * Add - Create WordPress Hook Actions for Google Analytics. * Add - Implement tracking with Actions Hooks. * Dev - Implement JS Build (ES6) and JS Lint. * Dev - Implement Javascript Building. = 1.7.1 - 2023-04-12 = * Fix - Bug with tracking enhanced ecommerce. = 1.7.0 - 2023-03-28 = * Dev - Load scripts via `wp_register_scripts` and `wp_eneuque_js`. * Fix - Avoid duplication of Google Tag Manager script. * Tweak - WC 7.6 compatibility. * Tweak - WP 6.2 compatibility. = 1.6.2 - 2023-03-07 = * Tweak - WC 7.5 compatibility. * Tweak - WP 6.2 compatibility. = 1.6.1 - 2023-02-15 = * Tweak - WC 7.4 compatibility. = 1.6.0 - 2023-01-31 = * Add - Common function for event code. * Fix - Add PHP unit tests. * Fix - Feature/consistency across gtag implementation. * Fix - Fix inconsistencies across item data in events. * Fix - Fix usage of tracker_var() in load_analytics(). = 1.5.19 - 2023-01-11 = * Fix - undefined WC constant. * Tweak - WC 7.3 compatibility. = 1.5.18 - 2022-12-14 = * Add - .nvmrc file. * Tweak - WC 7.2 compatibility. = 1.5.17 - 2022-11-09 = * Add - New Google Analytics task in WC. = 1.5.16 - 2022-11-03 = * Add - Declare compatibility for High Performance Order Storage. * Tweak - WC 7.1 compatibility. * Tweak - WP 6.1 compatibility. = 1.5.15 - 2022-10-04 = * Add - Support for a Google Tag ID. * Tweak - WC 7.0 compatibility. = 1.5.14 - 2022-09-02 = * Dev - Add branch-labels GH workflow. * Dev - GH release config and the new PR template. * Tweak - WC 6.9 compatibility. = 1.5.13 - 2022-08-03 = * Fix - Custom Order table compatibility. = 1.5.12 - 2022-07-27 = * Tweak - WC 6.8 compatibility. = 1.5.11 - 2022-07-06 = * Tweak - WC 6.7 compatibility. = 1.5.10 - 2022-06-07 = * Tweak - WC 6.6 compatibility. = 1.5.9 - 2022-05-10 = * Tweak - WC 6.5 compatibility. * Tweak - WordPress 6.0 compatibility. = 1.5.8 - 2022-02-02 = * Add - Support for Google Analytics cross domain tracking features. = 1.5.7 - 2022-01-13 = * Fix - Activation error when WC was disabled. * Tweak - WC 6.1 compatibility. = 1.5.6 - 2021-12-29 = * Fix - Confirm order key before displaying transaction tracking code. = 1.5.5 - 2021-12-09 = * Tweak - WC 6.0 compatibility. * Tweak - WP 5.9 compatibility. = 1.5.4 - 2021-11-10 = * Fix - Remove the slow order counting query from admin init. * Tweak - WC 5.9 compatibility. = 1.5.3 - 2021-09-15 = * Tweak - Avoid unnecessary completed orders queries. * Tweak - WC 5.7 compatibility. * Tweak - WP 5.8 compatibility. = 1.5.2 - 2021-07-30 = * Fix - Change utm_source and utm_medium in upsell notice link. * Fix - add product links to readme. = 1.5.1 - 2021-02-03 = * Tweak - WC 5.0 compatibility. = 1.5.0 - 2020-12-17 = * Add - Option to use Global Site Tag and the gtag.js library (for Universal Analytics or Google Analytics 4). * Add - Several new values added to the Tracker data. * Add - Developer ID for gtag.js and analytics.js. * Tweak - Bump minimum-supported WooCommerce version to 3.2. * Tweak - Remove deprecated jQuery .click(). * Fix - Settings link in plugins table row points directly to plugin settings. * Fix - Issue with multiple consecutive "Remove from Cart" events sent from the mini cart. = 1.4.25 - 2020-11-25 = * Tweak - WC 4.7 compatibility. * Tweak - WordPress 5.6 compatibility. = 1.4.24 - 2020-10-12 = * Tweak - WC 4.5 compatibility. = 1.4.23 - 2020-08-19 = * Fix - Prevent transaction from being tracked a second time when page is reloaded locally or from cache. * Tweak - WordPress 5.5 compatibility. = 1.4.22 - 2020-06-05 = * Tweak - WC 4.2 compatibility. = 1.4.21 - 2020-05-04 = * Tweak - WC 4.1 compatibility. = 1.4.20 - 2020-03-29 = * Fix - Change wc_goole_analytics_send_pageview fiter name to wc_google_analytics_send_pageview. = 1.4.19 - 2020-03-09 = * Tweak - WordPress 5.4 compatibility. = 1.4.18 - 2020-03-04 = * Tweak - Use code sniff version. * Tweak - WC 4.0 compatibility. = 1.4.17 - 2020-01-13 = * Tweak - Update constant VERSION in plugin file = 1.4.16 - 2020-01-13 = * Tweak - WC 3.9 compatibility. = 1.4.15 - 2019-11-04 = * Tweak - WC 3.8 compatibility. = 1.4.14 - 2019-09-04 = * Fix - Google Analytics JS URL missing quotes. = 1.4.13 - 2019-09-03 = * Tweak - Make Google Analytics JS script URL filterable. = 1.4.12 - 2019-08-13 = * Tweak - WC 3.7 compatibility. = 1.4.11 - 2019-08-02 = * Add - Filter to bypass "send pageview" for users whom want to use separate standard GA. `wc_goole_analytics_send_pageview`. * Fix - Revert last release due to it causing ecommerce tracking to be disabled when standard tracking is disabled. = 1.4.10 - 2019-07-10 = * Fix - Ensure universal analytics pageview doesn’t occur if standard tracking is disabled. = 1.4.9 - 2019-04-16 = * Tweak - WC 3.6 compatibility. = 1.4.8 - 2019-03-04 = * Fix - Event for deleting from cart not sent after a cart update. = 1.4.7 - 11/19/2018 = * Tweak - WP 5.0 compatibility. = 1.4.6 - 11/06/2018 = * Fix - Check for active WooCommerce plugin. = 1.4.5 - 10/16/2018 = * Tweak - Mention Google Analytics Pro in certain cases. * Tweak - WC 3.5 compatibility. = 1.4.4 - 03/20/2018 = * Fix - WC30 compatibility error when using deprecated get_product_from_item method. * Fix - Check object before using methods to prevent errors. * Fix - Variations not reporting category in cart tracking. * Add - Filter woocommerce_ga_disable_tracking added to disable tracking. * Tweak - Rebuilt languages pot file. = 1.4.3 - 06/15/2018 = * Fix - WC 3.x notice by using proper variation data. * Add - Option to track 404 (Not found) errors. = 1.4.2 - 09/05/2017 = * Fix - Missing Google Analytics ID. = 1.4.1 - 01/05/2017 = * Add - Filters for GA snippet (woocommerce_ga_snippet_head, woocommerce_ga_snippet_create, woocommerce_ga_snippet_require, woocommerce_ga_snippet_output) * Add - Option to toggle on/off Enhanced Link Attribution * Fix - JavaScript break by wrapping it in quotes * Fix - Use ID and SKU data in a consistent way so that all products are correctly tracked. * Fix - Updates for WooCommerce 3.0 compatibility. * Add - Settings link to the plugin in the Plugins screen * Fix - Fatal error on shortcode usage for empty product = 1.4.0 - 20/11/2015 = * Feature - Support for enhanced eCommerce (tracking full store process from view to order) * Tweak - Setting up the plugin is now clearer with some helpful links and clearer language * Tweak - New filter on the ga global variable * Refactor - JavaScript generation functions have been moved to their own class = 1.3.0 - 12/11/2014 = * Feature - Added the transaction currency in the tracking code * Feature - Add data privacy option that are mandatory in some countries * Tweak - Moved the tracking code to the head of the page * Tweak - Remove the "SKU" prefix to the sku for addItem * Refactor - Integration class reformulated = 1.2.2 - 15/10/2014 = * Feature - Adding option to anonymize IP addresses * Feature - Adding gaOptOut function to be called from any page for OptOut = 1.2.1 - 17/09/2014 = * Tweak - Adding utmnooverride to return url for Google Adwords = 1.2.0 - 28/07/2014 = * Feature - Adding display advertising parameter to Universal Analytics * Fix - Using get_total_shipping() instead of get_shipping * Fix - Using wc_enqueue_js() instead of $woocommerce->add_inline_js( * Tweak - Updating plugin FAQ * Tweak - Adding parenthesis for clarity = 1.1 - 29/05/2014 = * Added option to enable Display Advertising * Added compatibility support for WooCommerce 2.1 beta releases = 1.0 - 22/11/2013 = * Initial release