Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update tracking for classic pages #328

Merged

Conversation

martynmjones
Copy link
Contributor

@martynmjones martynmjones commented Nov 10, 2023

Changes proposed in this Pull Request:

This is a major restructuring centered around a new Tracker utility which manages all Google Analytics events triggered by either WooCommerce Blocks or classic pages. All tracked events must have an accompanying data formatter in order for the Tracker to send the event.

Several files and tests have been removed which are no longer of use

Screenshots:

Screenshot 2024-01-25 at 17 36 37

Test setup

Debug a test website via Tag Assistant that has both Block powered and classic pages for the Cart, Checkout, and Product Listings (Using the All Products Block). Ensure all Event Tracking options are enabled in WooCommerce > Settings > Integrations > Google Analytics.

Detailed test instructions:

Work through all test instructions using both types of pages while not logged into the site as an admin.

  1. Visit a product archive page and confirm that one view_item_list event is sent containing all the products on the page
  2. Click on a product
  3. Confirm that a select_content event is sent for that product
  4. After the single product loads, confirm that a view_item event is sent for the product and a view_item_list event is sent if any related products or other lists are displayed
  5. Add the product to cart and confirm the add_to_cart event is sent
  6. Visit the cart, remove the product from the cart and confirm the remove_from_cart event it sent
  7. Go back to the product archive page and add products to cart from there confirming the event is sent for each
  8. Visit the checkout and confirm a begin_checkout event is sent
  9. Place the order and one the thank you page confirm a purchase event is sent
  10. Run some basic smoke tests

Additional

  1. Disable some options in WooCommerce > Settings > Integrations > Google Analytics
  2. Confirm those events are no longer sent
  3. Adjust the Product Identification settings
  4. Confirm that the data sent with each event includes the correct product identifier structure

⚠️ This branch also includes the changes needed to rename the extension to Google Analytics for WooCommerce (See #353).

Changelog entry

Update - Add shared tracking functionality for WooCommerce Blocks and classic pages

@martynmjones martynmjones self-assigned this Nov 10, 2023
@github-actions github-actions bot added the changelog: update Big changes to something that wasn't broken. label Nov 10, 2023
Copy link
Member

@tomalec tomalec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the idea I get from the brief description of the approach in the P2.
However, I'm not sure I fully understand specifics and implementation.

I tried to simplify the implementation logic a bit, maintaining more-or-less the same behavior.
By proposal is at https://github.com/woocommerce/woocommerce-google-analytics-integration/compare/update/tracking-for-classic-pages...update/tracking-for-classic-pages-tracker-class?expand=1

Please, let me know if that makes sense to you and still goes in the direction you envision.

I think there is still room for simplification in behavior and logic in both branches :)

I'd appreciate a F2F call, to discuss the details.

assets/js/src/tracker/index.js Outdated Show resolved Hide resolved
assets/js/src/tracker/index.js Outdated Show resolved Hide resolved
assets/js/src/index.js Outdated Show resolved Hide resolved
@martynmjones martynmjones requested a review from tomalec February 9, 2024 17:12
@tomalec
Copy link
Member

tomalec commented Feb 19, 2024

When I try to render the cart page, it throws an error:

nginx_1      | 2024/02/19 15:46:38 [error] 45#45: PHP Fatal error:  Uncaught Error: Cannot unpack array with string keys in /var/www/html/wp-content/plugins/woocommerce-google-analytics-integration/includes/class-wc-abstract-google-analytics-js.php:174
nginx_1      | Stack trace:
nginx_1      | #0 [internal function]: WC_Abstract_Google_Analytics_JS->{closure}()
nginx_1      | #1 /var/www/html/wp-content/plugins/woocommerce-google-analytics-integration/includes/class-wc-abstract-google-analytics-js.php(178): array_map()
nginx_1      | #2 /var/www/html/wp-content/plugins/woocommerce-google-analytics-integration/includes/class-wc-abstract-google-analytics-js.php(68): WC_Abstract_Google_Analytics_JS->get_formatted_cart()
nginx_1      | #3 /var/www/html/wp-includes/class-wp-hook.php(324): WC_Abstract_Google_Analytics_JS->{closure}()
nginx_1      | #4 /var/www/html/wp-includes/class-wp-hook.php(348): WP_Hook->apply_filters()
nginx_1      | #5 /var/www/html/wp-includes/plugin.php(517): WP_Hook->do_action()
nginx_1      | #6 /var/www/html/wp-content/plugins/woocommerce/templates/cart/cart.php(20): do_action()

Did we drop PHP 7.x support?

@martynmjones
Copy link
Contributor Author

When I try to render the cart page, it throws an error:

nginx_1      | 2024/02/19 15:46:38 [error] 45#45: PHP Fatal error:  Uncaught Error: Cannot unpack array with string keys in /var/www/html/wp-content/plugins/woocommerce-google-analytics-integration/includes/class-wc-abstract-google-analytics-js.php:174
nginx_1      | Stack trace:
nginx_1      | #0 [internal function]: WC_Abstract_Google_Analytics_JS->{closure}()
nginx_1      | #1 /var/www/html/wp-content/plugins/woocommerce-google-analytics-integration/includes/class-wc-abstract-google-analytics-js.php(178): array_map()
nginx_1      | #2 /var/www/html/wp-content/plugins/woocommerce-google-analytics-integration/includes/class-wc-abstract-google-analytics-js.php(68): WC_Abstract_Google_Analytics_JS->get_formatted_cart()
nginx_1      | #3 /var/www/html/wp-includes/class-wp-hook.php(324): WC_Abstract_Google_Analytics_JS->{closure}()
nginx_1      | #4 /var/www/html/wp-includes/class-wp-hook.php(348): WP_Hook->apply_filters()
nginx_1      | #5 /var/www/html/wp-includes/plugin.php(517): WP_Hook->do_action()
nginx_1      | #6 /var/www/html/wp-content/plugins/woocommerce/templates/cart/cart.php(20): do_action()

Did we drop PHP 7.x support?

Apologies @tomalec, I've pushed an updated so you should no longer get that error 9f60881.

Copy link
Member

@tomalec tomalec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for all the changes and clarifications.

I left some comments. Many are cosmetic ones. The most concerning to me are:

Also, while testing, I do not get remove_from_cart event triggered when I remove a variable item from the cart.
Screencast from 19.02.2024 19:21:07.webm

The trackerEventHandler is called, but fails with

index.js:15 Uncaught TypeError: Cannot read properties of undefined (reading 'variation')
    at getProductFieldObject (index.js:15:15)
    at remove_from_cart (data-formatting.js:62:33)
    at trackerEventHandler (index.js:72:5)
    at HTMLFormElement.<anonymous> (classic.js:68:47)

@tomalec
Copy link
Member

tomalec commented Feb 19, 2024

Seems there is an id mismatch
image

@martynmjones
Copy link
Contributor Author

The changes we discussed earlier have been made and the ID mismatch has been resolved so this is ready for another round @tomalec. Thanks!

Comment on lines 109 to 110
// Return early if the user has clicked on anything other
// than a product link or an Add to cart button.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💅 Sorry, but as a non-native English speaker I read it as "the user has clicked on anything other than (a product link or an Add to cart button)" and I think you mean "the user has clicked on (anything other than a product link) or an Add to cart button", maybe something like this would be safer:

Suggested change
// Return early if the user has clicked on anything other
// than a product link or an Add to cart button.
// Return early if the user has clicked on
// an "Add to cart" button or anything other than a product link

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for highlighting that! Updated in 94cc036

Comment on lines 111 to 125
const targetLink = event.target.closest(
'.woocommerce-loop-product__link'
);

const isButton = event.target.classList.contains( 'button' );

const isAddToCartButton =
event.target.classList.contains( 'add_to_cart_button' ) &&
! event.target.classList.contains(
'product_type_variable'
);

if ( ! targetLink && ( ! isButton || isAddToCartButton ) ) {
return;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💅
I got a gut feeling that this selector may be hard to keep in sync to match with WC core/theme changes.

Should we fire the add_to_cart event for non-ajax buttons as well?
From reading WC Core code, I think we can disable ajax_add_to_cart globally or for a product, then end up with a
<a class="button add_to_cart_button">Add to cart</a>.
If we want to fire for those, then the !isButton condition should be removed. Otherwise, we could use .ajax_add_to_cart to precisely select only those add-to-cart-like buttons that actually add to cart, guarding against .product_type_variable to any other.

Are you sure we will not have some other .button in the product card that does not actually select the product, but does some other thing? Like a link to a promotion, group, brand site, etc?
Maybe we can identify "Add to cart"-likeness by having data-product_id attribute :)
So we would do

Suggested change
const targetLink = event.target.closest(
'.woocommerce-loop-product__link'
);
const isButton = event.target.classList.contains( 'button' );
const isAddToCartButton =
event.target.classList.contains( 'add_to_cart_button' ) &&
! event.target.classList.contains(
'product_type_variable'
);
if ( ! targetLink && ( ! isButton || isAddToCartButton ) ) {
return;
}
const isProductLink =
// Regular product link.
event.target.closest( '.woocommerce-loop-product__link' ) ||
// Add-to-cart-like button.
event.target.hasAttribute( 'data-product_id' );
const isAddToCartButton =
event.target.classList.contains( 'add_to_cart_button' ) &&
! event.target.classList.contains(
'product_type_variable'
);
if ( ! isProductLink || isAddToCartButton ) {
return;
}

Also, all this confusion looks like an encouragement to champion a PR to WC Core to add the product_id datar attribute to the product card ;)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When clicking on non-ajax add to cart button the event will be sent when the page loads and the confirmation message is displayed so I don't think we need additional targeting there.

I've added a check like you suggested so that the event will only send if the button includes the data-product_id attribute to reduce the chance of issues with other extensions in 94cc036.

Copy link
Member

@tomalec tomalec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the changes and explanations.
Left a few tweak ideas
LGTM.

@martynmjones martynmjones merged commit 3dca31f into remove-universal-analytics Feb 27, 2024
6 checks passed
@martynmjones martynmjones deleted the update/tracking-for-classic-pages branch February 27, 2024 17:11
@jorgemd24 jorgemd24 mentioned this pull request Mar 5, 2024
19 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
changelog: update Big changes to something that wasn't broken.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants