���� 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.txt 0000644 00000005722 14673113014 0006550 0 ustar 00 === 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.php 0000644 00000002657 14673113014 0015010 0 ustar 00 get_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.php 0000644 00000025073 14673113014 0016260 0 ustar 00 attach_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.php 0000644 00000034223 14673113014 0014042 0 ustar 00 settings );
}
/**
* 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(
'',
'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.php 0000644 00000023002 14673113014 0013400 0 ustar 00 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.php 0000644 00000025402 14673113014 0015357 0 ustar 00 maybe_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.js 0000644 00000013552 14673113014 0011051 0 ustar 00 (()=>{"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.php 0000644 00000000151 14673113014 0012331 0 ustar 00 array('wp-hooks', 'wp-i18n'), 'version' => 'c4a77335eae7e6132482');
changelog.txt 0000644 00000027135 14673113014 0007244 0 ustar 00 *** 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