Support Google Analytics 4

Created on 3 January 2021, almost 4 years ago
Updated 2 February 2023, almost 2 years ago

Required actions:

  • Rename event parameters (done)
  • Restructure parameters as necessary (mostly done)
  • Switch checkout steps to standardized begin_checkout / add_shipping_info / add_payment_info (needs to find the relevant panes on the page)
Feature request
Status

Needs review

Version

2.0

Component

Code

Created by

🇺🇸United States djween

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇺🇸United States jcmartinez Raleigh, NC, USA

    It may be possible that this module works well with the patch, but I can't tell because the current README file and the instructions located at https://www.drupal.org/docs/8/modules/commerce-google-tag-manager/setup-... look more specific to the older version of Google Analytics (GA).

    Can anyone document briefly how to use this with GA4 and GTA?

    Thanks for the good work!

  • 🇬🇧United Kingdom Dubs

    Thanks for all the work so far :-)

    I've added a new patch which includes some other DL variables such as currency and value. Also products has been changed to items to match the documentation on Google in some of the DL arrays. Lastly, there's a view_cart event added.

    Please review, and let me know your thoughts...

    Thanks :-)

  • 🇮🇹Italy trickfun

    Hi Dubs,
    i can't apply the patch on 8.x-2.x-dev

  • 🇮🇹Italy gatiba

    Same here on 8.x-2.0-beta1.

  • 🇧🇪Belgium michiellucas

    Does anyone know how to configure this in Google Tag manager?

  • 🇬🇧United Kingdom Dubs

    @trickfun and @gatiba. I just removed and re-added 2.x-dev, but it did apply for me. Do you know which lines failed so I can check?

  • 🇬🇧United Kingdom Dubs

    Here's the patch regenerated again - please try this one :-)

  • 🇮🇹Italy trickfun

    Now i can apply the patch.
    thank you

  • 🇮🇹Italy trickfun

    I Dubs. in my patch i setup correct GA4 event keys.
    https://www.drupal.org/files/issues/2022-08-12/3190724-compatible-with-g...

    this is the GA4 official docs https://developers.google.com/analytics/devguides/collection/ga4/ecommer...

    why don't you use it?
    i view old event keys like viewCart, productClick.

    what is wrong?
    thank you

  • 🇧🇪Belgium michiellucas

    Trickfun, just tested your patch and it works fine if you adjust your GTM container to use GT4 events.

    Thanks, using it now in production.

    Would be nice to have all the events from GT4

  • 🇮🇹Italy trickfun

    Sorry michiellucas but i don't understand.

    when you call the EVENT_ADD_CART event, you built GA4 message with UA event key
    you use EVENT_ADD_CART constant with "addToCart" value instead of "add_to_cart" one.

    you can see the GA4 events key here

    https://developers.google.com/analytics/devguides/collection/ga4/ecommer...

    i think the right constant in EventTrackerService file are:

    const EVENT_PRODUCT_IMPRESSIONS = 'view_item_list';
    const EVENT_PRODUCT_DETAIL_VIEWS = 'view_item';
    const EVENT_PRODUCT_CLICK = 'select_item';
    const EVENT_ADD_CART = 'add_to_cart';
    const EVENT_REMOVE_CART = 'remove_from_cart';
    const EVENT_VIEW_CART = 'view_cart';
    const EVENT_CHECKOUT = 'begin_checkout';
    const EVENT_PURCHASE = 'purchase';
    
    

    i'm wrong?
    if yes, how can adjust GTM container to user GA4 events?

    thank you

  • 🇧🇪Belgium michiellucas

    Hey,

    i mean everything works well with your patch, i just had to rename some of my events (UA to G4)

    But we should implement some more events like add_payment_info and add_shipping_info

    Thanks for the patch!

    Michiel

  • 🇺🇸United States djween

    Hi, to add on to #29... I implemented patch in #27 but my GA4 ecommerce events are not triggering in GTM. It seems to be outputting UA event name and not GA4 name. For example: outputting: addToCart instead of add_to_cart.

    I am looking at this documentation (see bottom of this page): https://developers.google.com/analytics/devguides/migration/ecommerce/gtm-ga4-to-ua

    Thank you.

  • 🇺🇸United States djween

    Also when I test in GTM preview feature, I see UA data layer format and not GA gtag.js API format for data output.
    I see that this is injected on my page:

      window.dataLayer = window.dataLayer || [];
      function gtag(){dataLayer.push(arguments);}

    Not sure if I am just seeing it this way because it seems like it is still using UA event names?

  • 🇬🇧United Kingdom Dubs

    @trickfun - you're right. They should not have been changed. Let me see if it can be changed back.

  • 🇺🇸United States zipymonkey Durham, NH

    I tried to combine the changes from #27 and #17, so GA4 recommended ecommerce events are used and this tracks quantity updates in the cart. Hopefully, I didn't miss anything but this appears to be working using the GA4 debugging tools.

  • 🇮🇹Italy trickfun

    Can you change attribute $eventStorage visibility?
    from private to protected?

    I need to extend checkoutStep function to build my own logic but i can't because

    $this->eventStorage->addEvent($data);
    

    is not available.
    Thank you

  • 🇨🇦Canada sagesolutions

    For people looking on how to configure GA4 in GTM, there is a nice walkthrough at

    https://www.drupal.org/docs/contributed-modules/commerce-google-tag-mana...

    However, its a bit old and needs to be updated.

    For GA4, you will first need to create a GA4 configuration with your G- ID. Instructions are found here:

    https://support.google.com/tagmanager/answer/9442095?hl=en

    Next, you will need to setup GA4 tags (the addToCart, removeFromCart, productDetailsViews, checkout and purchase) Instructions are found here:

    https://support.google.com/tagmanager/answer/13034206?sjid=1322678400662...

    Previously I had tags setup for UA tracking, so I copied them and updated the tag type and other details. See addToCartTag screenshot.

    I hope this helps others setting up GTM!

  • Status changed to Needs work over 1 year ago
  • 🇨🇦Canada sagesolutions

    After some testing, I see that events are coming in to GA4, but the purchase data is missing. Looking into it, the proper purchase function should be updated to this:

    public function purchase(OrderInterface $order) {
        $data = [
          'event' => self::EVENT_PURCHASE,
          'ecommerce' => [
            'transaction_id' => $order->getOrderNumber(),
            // The value should be the total value (incl. tax and shipping).
            'value' => self::formatPrice((float) $order->getTotalPrice()->getNumber()),
            'tax' => $this->formatPrice($this->calculateTax($order)),
            'shipping' => self::formatPrice($this->calculateShipping($order)),
            'currency' => $order->getTotalPrice()->getCurrencyCode(),
            'coupon' => $this->getCouponCode($order),
            'items' => $this->buildProductsFromOrderItems($order->getItems()),
          ],
        ];
    
        $this->eventStorage->addEvent($data);
      }
    

    Also as an FYI, the event names in GTM should match the new event names in code:

    
      const EVENT_PRODUCT_IMPRESSIONS = 'view_item_list';
      const EVENT_PRODUCT_DETAIL_VIEWS = 'view_item';
      const EVENT_PRODUCT_CLICK = 'select_item';
      const EVENT_ADD_CART = 'add_to_cart';
      const EVENT_REMOVE_CART = 'remove_from_cart';
      const EVENT_CHECKOUT = 'begin_checkout';
      const EVENT_PURCHASE = 'purchase';
    
  • 🇬🇧United Kingdom retrodans

    We wanted to try out this patch, but it wouldn't apply to beta or dev for me. So I have refactored a patch to work for 2.0.0-beta1 and figured it might be worth sharing in case others want to test this out to help. I am afraid it doesn't take into account the ideas since comment #36, as was just a refactor.

  • 🇷🇴Romania cslevy

    Thank you for the patch, but I think that in the viewCart event listener is missing some kind of conditions. At the moment the event is triggered on every page.

  • 🇩🇪Germany a.dmitriiev

    I found that remove_from_cart event doesn't need remove wrapper around items. Here is a re-roll of 40 with changes in interdiff

  • 🇨🇦Canada sagesolutions

    @a.dmitriiev the remove_from_cart event updates are already in the Merge Request.

    @retrodans a lot of your changes in patch #40 are also already in the MR. Please update the MR with the view_cart event tracking

    @retrodans a couple things I found need changing:

    1) You have created new setItemCategoryN functions but you need to create the 5 item_categoryN variables in the class.

    2) Since you are adding / renaming variables like private $item_name; please add the variable type. For example, it should be private string $item_name;

    3) For all functions you have changed, add the function's return type.

    I.e.

    public function getItemCategory1() {
        return $this->item_category1;
      }
    

    is now

    public function getItemCategory1(): string  {
        return $this->item_category1;
      }
    

    4) Add a condition to the viewCart event listener so it doesnt trigger on every page as per @cslevy's comment in #41

    Thanks everyone for your work on this module!

  • 🇬🇧United Kingdom retrodans

    @sagesolutions thanks for the comments, I have made amends for 1/2/3

    I haven't done 4 though, as not sure whether I know enough about it to implement the change. A lot of this was already there from one of the early patches in comment #9, I just refactored for the newest branch. I can see it is being added as a KernelEvent, and imagine there was a reason it was put here rather than using one of the cart hooks, why was that? As before I mess with conditions, it might be good to understand why it is a Kernel event.

  • 🇨🇦Canada sagesolutions

    @retrodans thanks for the quick updates for 1-3.

    For #4, I agree the trackCartView should be triggered on the KernelEvents::REQUEST event.

    However, I think what @cslevy meant was in that trackCartView function, there should be a check if you are on the cart page before running $this->eventTracker->cartViews($cart);

    Currently, it would trigger a view_cart event on every page load if the cart wasn't empty, which is not what we want.

    Instead, we want to trigger a view_cart event whenever the user loads the /cart page. (Cart can be empty and I think we should still trigger the event for this case). The trackProductView function does a similar check for product pages.

  • 🇨🇭Switzerland berdir Switzerland
    +++ b/src/Product.php
    @@ -12,56 +12,119 @@ class Product {
        *
        * @var string
        */
    -  private $id;
    +  private string $id;
     
       /**
        * The price.
    

    adding non-nullable types to these properties causes errors when using order items that are not products:

    TypeError: Cannot assign null to property Drupal\commerce_google_tag_manager\Product::$item_id of type string in Drupal\commerce_google_tag_manager\Product->setItemId()

    +++ b/src/Product.php
    @@ -188,8 +251,8 @@ class Product {
        */
    -  public function getCategory() {
    -    return $this->category;
    +  public function getItemCategory(): string {
    +    return $this->item_category;
    

    These method names are API changes that will require a new major version, our customization on top of this is broken currently. I think it's worth considering to not do that, keep make it easier to transition to this even if the API doesn't quite match the new terminology from ga4.

    I'm also seeing some issues with begin checkout event, that doesn't seem to fire at least when you have optional pages in your checkout configuration, like shipping or login/register. Will need to investigate.

  • Status changed to Needs review over 1 year ago
  • 🇨🇭Switzerland berdir Switzerland

    So, quite a lot of changes, but it's starting to work for our use cases.

    * I restored the original method names and also adjusted slightly the toArray() implemention for array values, so that the first one has no number suffix, the following ones then have 2, 3, ... With that, category no longer requires 5 different properties, you can set it as string or array. I also removed dimensions and metrics, doesn't seem to exist in the new API.
    * Made all properties nullable
    * Implemented the begin checkout event based on the order getting a checkout flow, that's resolved once the first time you start checkout, seems to work well for me. removed the whole separate kernel event subscriber. the Checkout::INIT issue that's referenced earlier pretty much uses the same idea.
    * Fixed begin checkout data similar to others, with just items without wrapper.

    There's definitely still work to do, I'm sure tests will need updates, there is the cart view stuff, which doesn't work for us anyway as it hardcodes the default order type. And then there's the new separate shipping and payment info events, but those can be follow-ups.

    I did reach out to the most recent maintainer about maintainer access.

  • 🇦🇹Austria agoradesign

    I've added Support Google Tag 2.x Module Active as related issue, where I've ask whether this module is needed anyway, when google_tag 2.x does already support Commerce ootb - is there any extra functionality provided by this module then?

  • 🇬🇷Greece giorgosk Chios, Greece 🇬🇷

    Updated patch from 47
    - drupal 10 compatibilities from https://www.drupal.org/node/3340566
    - other drupal 10 fixes
    - cart_view only fires on /cart page (as suggested above)
    - applies to "drupal/commerce_google_tag_manager": "2.x-dev@dev",

    can consider this patch D10 and GA4 compatible

  • 🇬🇷Greece giorgosk Chios, Greece 🇬🇷

    Adding a small check for cart being not null

  • 🇨🇭Switzerland berdir Switzerland

    We've switched over to google_tag as well now. I've created Allow to alter order item data for commerce events Needs review to add similar alter functionality as this module had. There are still a few gaps, like some checkout steps, but google_tag also does some things better, it is for example way more performant as it doesn't need the extra request on every page.

    Consider this module abandoned and unsupported and migrate to google_tag.

  • 🇺🇸United States djween

    @Berdir or anyone else. I'm testing removing this module and only using google_tag as suggested above. In my testing when using google_tag alone, the ecommmerce events are firing (for example: add_to_cart) but I'm not seeing the data layer values that were coming over with this module (commerce_google_tag_manager). For example, in google's tag assistant preview I see the following in the data layer when using commerce_google_tag_manager:

    ecommerce: {
    currencyCode: "USD",
    add: {
    products: [
    {
    name: "widget ABC",
    id: "7463",
    price: "630.00",
    variant: "widget ABC - red",
    quantity: 1
    }

    but not when using google_tag. Any ideas would be appreciated.

  • 🇺🇦Ukraine dench0

    Fix src/Event/TrackCheckoutStepEvent.php use statement.

Production build 0.71.5 2024