How-To Guide: Tracking On-site Promotions with GTM

  • How-To Guide: Tracking On-site Promotions with GTM

How-To Guide: Tracking On-site Promotions with GTM

Attracting the right visitors to your website and encouraging them to accomplish a desired outcome can often feel like laying out a trail of breadcrumbs for them to follow.

In-Store PromotionsThe trail may start from a post on Facebook, a Google search ad, or an email newsletter, from which the person arrives to your website. You may then lay out some hero images, featured posts, or sidebar links to lead them deeper into your site. And finally, you may encourage the visitor to submit a form, download a brochure, or make a purchase.

When it comes to analyzing this customer journey and optimizing your marketing activities, you’ll want to ensure that you can track every step; every breadcrumb in the trail. In fact you’ll want to track every trail, as there are likely many paths each visitor could follow to the same destination.

If you have Google Analytics, you are likely familiar with using “utm” parameters to track inbound campaigns and Goals to track key outcomes. But what do you use to track the path of visitors through your site on the way to completing those outcomes?

You may know that 5% of visitors from LinkedIn downloaded your whitepaper, but how many of them got there by clicking the hero image vs. the link in the sidebar?

The rest of this post is a how-to guide on setting up internal promotion tracking in GA through Google Tag Manager. With a little bit of effort, you too can measure the effectiveness of your on-site promotions!

Prior to the introduction of Internal Promotion tracking in GA, tracking on-site campaigns was often done in one of the following ways:

  • Leveraging the Site Search reports. For example, see this post by Justin Cutroni.
  • Tracking events for clicks on promotional links.
  • Adding custom query parameters to promotional links.

Although these methods provide information on how frequently your internal promotions are being clicked, it is challenging to see how each promotion is contributing to a certain goal conversion.

Internal Promotion tracking is part of Enhanced Ecommerce features in Universal Analytics. But it’s certainly not just for ecommerce sites! You can enable Enhanced Ecommerce and use the Internal Promotion reports even if you are not tracking ecommerce transactions in GA.

How to Implement Internal Promotion Tracking

1. Enable Enhanced Ecommerce in Google Analytics

  1. In your GA admin panel, select the desired view and click on Ecommerce Settings
  2. Switch on Enable Ecommerce (if not already enabled)
  3. Switch on Enhanced Enhanced Ecommerce Reporting

Remember, you do not need to sell anything online in order to enable this. If you are using Ecommerce tracking in GA already, but not Enhanced E-commerce, you should be able enable Enhanced Ecommerce without any impact on your tracking, but we recommend first testing in a separate view.

With respect to internal promotion tracking, enabling Enhanced Ecommerce gives you access to four built-in dimensions to capture information about your promotionscc_intpromo_05:

  1. Name: e.g. Summer Sale
  2. ID: e.g. PROMO_1234
  3. Position: e.g. banner_slot_1
  4. Creative: e.g. summer_banner_2

(Note that either Name or ID field is required with other fields being optional)

Enhanced Ecommerce also provides a pre-built Internal Promotions report. Once enabled, you will find it under the Conversions section in GA.

Once you start collecting data on impressions and clicks of your internal promotions, your report will look something like this:

Internal Promotions Report Example

GA automatically calculates a click-through rate (CTR) for each promotion and shows you conversions that occurred as a result. Just like other standard GA reports, you can switch the primary dimension, add a secondary dimension, and view different conversion metrics.

Now that we have an idea of what this should look like once we are done, let’s send information about our promotions to GA.

2. Tag Internal Promotion Links

To identify and label our internal promotions, you can use custom URL query parameters. This is often the easiest way of adding information into promotional links that are managed through a CMS. It also provides an efficient transition in the case you are already tracking internal promotions through URL parameters (e.g. using site search).

We will use four URL query parameters:

  • promo_name
  • promo_id
  • promo_creative
  • promo_position

(Note: If you already have your own custom parameters in your promo links, you can use those instead.)

These parameters should be added to all promotional links that we wish to track. Note that only one of promo_name or promo_id is required; the other parameters are optional.

For example, if we have a promotion for a “Spring Sale” located in our top banner, the link may look like this:

<a href="">Spring Sale</a>

Note that there are other methods for making promotion information available (e.g. HTML attributes, data layer). As long as the information is available on the page, you can configure GTM to capture it and send it to GA with your promotion impressions and clicks.

3. Configure Tracking in Google Tag Manager

Once all of that is done, we will configure GTM to pick up this information and send it to GA. We need to set up a total of 4 variables, 5 triggers and 3 tags for this.

First, we need to create our variables:

  1. Create “Promo Name” variable:
    • Create new Auto-Event Variable
    • Set Variable Type to Element URL
    • Set Component Type to Query
    • Enter promo_name in the Query Key
      Promo Name Variable
  2. Next we will create 3 variables that have similar configuration with the only difference in “Query Key” parameter:
    • Promo ID with Query Key set to promo_id
    • Promo Creative with Query Key set to promo_creative
    • Promo Position with Query Key set to promo_position

Next, create our triggers:

  1. “DOM Ready” Trigger. (Check first to see if you already have a DOM Ready trigger configured):
    • Create new Page View – DOM Ready trigger.
    • Fire on All DOM Ready Events.DOM Ready Trigger
  2. “Click – Promo Click – ID found”:
    • Create new Click trigger for Just Links.
    • Fire on {{Promo ID}} matches RegEx (ignore case) .+Click - Promo Click - ID found trigger
  3. “Click – Promo Click – Name found”:
    • Create new Click trigger for Just Links.
    • Fire on {{Promo Name}} matches RegEx (ignore case) .+Click - Promo Click - Name found trigger
  4. “Internal Promotions View” trigger:
    • Create new Custom Event trigger.
    • Set the event name to promotionView
    • Set trigger to fire on all custom events.Event - Internal Promotions View trigger
  5. “Internal Promotion Click” trigger:
    • Create new Custom Event trigger.
    • Set the event name to promotionClick 
    • Set trigger to fire on all custom events.Event - Internal Promotion Click trigger

Finally we will set up our tags:

  1. Custom HTML tag to track promotion views. This tag should fire on the “DOM Ready” trigger and it will contain the following code:
    <script type="text/javascript">
    (function () {
     "use strict";
     var internalPromotions = {
     promos: [],
     count: 0
     var promo_name='promo_name';//change to your query parameter if needed
     var promo_id='promo_id';//change to your query parameter if needed
     var promo_creative='promo_creative';//change to your query parameter if needed
     var promo_position='promo_position';//change to your query parameter if needed
     function getParameterByName(name, url) {
     var regex = new RegExp("[?&]" + name.replace(/[\[\]]/ig, "\\$&") + "(=([^&#]*)|&|#|$)");
     var results = regex.exec(url);
     if (!results) return null;
     if (!results[2]) return null;
     return decodeURIComponent(results[2].replace(/\+/ig, " "));
"a")).forEach(function (element) {
     if (element.getAttribute("href") !== null && element.getAttribute("href") !== undefined) {
     if (element.getAttribute("href").match(new RegExp(promo_name, 'ig')) !== null || element.getAttribute("href").match(new RegExp(promo_id, 'ig')) !== null) {
     if (element.getAttribute("href").match(new RegExp(promo_name, 'ig')) !== null){
     internalPromotions.promos[internalPromotions.count].name = getParameterByName(promo_name, element.getAttribute("href"));
     console.log(element.getAttribute("href").match(new RegExp(promo_name, 'ig')));
     if (element.getAttribute("href").match(new RegExp(promo_id, 'ig')) !== null){
     internalPromotions.promos[internalPromotions.count].id=getParameterByName(promo_id, element.getAttribute("href"));
     if (element.getAttribute("href").match(new RegExp(promo_position, 'ig')) !== null){
     internalPromotions.promos[internalPromotions.count].position=getParameterByName(promo_position, element.getAttribute("href"));
     if (element.getAttribute("href").match(new RegExp(promo_creative, 'ig')) !== null){
     internalPromotions.promos[internalPromotions.count].creative=getParameterByName(promo_creative, element.getAttribute("href"));
     if (internalPromotions.count > 0) {
     'event': 'promotionView',
     'ecommerce': {
     'promoView': {
     'promotions': internalPromotions.promos
  2. Custom HTML tag that will track promotion clicks. This tag should fire on the “Click – Promo Click – ID found” and “Click – Promo Click – Name found” triggers and it will contain the following code:
    <script type="text/javascript">
    (function() {
     "use strict";
     var promo_name = {{Promo Name}};
     var promo_id = {{Promo ID}};
     var promo_creative={{Promo Creative}};
     var promo_position={{Promo Position}};
     var promoClickData = {};
     if ((promo_name !== undefined && promo_name.length > 0) || (promo_id !== undefined && promo_id.length > 0)) {
     if (promo_name !== undefined && promo_name.length > 0) { = promo_name;
     if (promo_id !== undefined && promo_id.length > 0) { = promo_id;
     if (promo_creative !== undefined && promo_creative.length > 0) {
     promoClickData.creative = promo_creative;
     if (promo_position !== undefined && promo_position.length > 0) {
     promoClickData.position = promo_position;
     'event': 'promotionClick',
     'ecommerce': {
     'promoClick': {
     'promotions': [promoClickData]
  3. Finally, we will set up a separate GA Tag to track promotion impressions and clicks. It will have the following configuration and will load on both Internal Promotions triggers we created:

GA Tag to track impressions and clicks

Test, publish and you are done!

Let us know if you have any questions, comments, or suggestions about tracking internal promotions in Google Analytics

By |2024-03-15T10:04:31-04:00April 27, 2016|55 Comments


  1. reinier 2016-11-02 at 06:42 - Reply

    We have a slider, but even the promotions we don’t see are coming in as viewed. How can we solve this problem?

    • Max Bondarenko 2016-11-07 at 10:07 - Reply

      Hi Reiner,

      The script provided assumes all promotions are visible on the page. You would need to modify it to ensure that only visible promotions are sent. Perhaps you can use ideas that are used in ReadJS plugin. We are working on a new script that takes visibility into account but could not give you an indication on when that would be released to the public.

  2. Suzanne Karzoun 2016-12-21 at 17:10 - Reply

    I was wondering if there was a solution to the visibility of the promotions issue yet. I am having the same problem with our drop-down menus.

    • Max Bondarenko 2016-12-23 at 08:28 - Reply

      Hello Suzanne,

      We are still deciding on wherever to release this kind of tracking to general public, given how much work we put into it.

      • Jenna 2021-08-04 at 20:26 - Reply

        Hi Max,

        Is this something that is still unavailable to the public?

        Thank you

        • Hayley Yacynuk 2021-08-06 at 14:08 - Reply

          Hi Jenna, thank you for your question.

          Unfortunately we will not be releasing that script to the public as it involved significant time investment on our side. We apologize for any inconvenience. If you would like further information and to continue this conversation, please contact us directly by filling out our contact form, linked here.

          I hope this helps answer your question! We look forward to further conversations.

  3. Terry 2017-03-07 at 07:25 - Reply

    Hi. Wondering if there has been an update to this process / code based no the update to tag manager and if the visibility issue has been resolved here. We regularly put promotions in sliders so I’d like to know that they are tracked properly when clicked.

    • Max Bondarenko 2017-03-09 at 10:17 - Reply

      Hi Terry,

      Outside of minor interface changes in GTM, I believe that the process of adding internal promotion tracking remains the same. Do let me know if there is specific issue that I might have overlooked.

      In terms of the scripts – they still work for both clicks and impressions. The only difference in this case is that impressions are sent for all promotions on the page without regards for their visibility (this would inflate the number of actual impressions). Clicks, on the other hand, should be tracked as expected – they are sent only when person clicks on a promotion. If you do notice any specific issues with this scripts – do let me know and I will try to address them.

      In regards to promotion visibility – while we do have an updated version of the script that tracks which exact pieces of content were visible and sends impressions only for those elements – we will not be releasing that script to public as it involved significant time investment on our side.

  4. Ajay 2017-03-16 at 04:01 - Reply

    How can i track banner impression of publisher in GA with GTM with above tricks

    • Max Bondarenko 2017-03-16 at 07:05 - Reply

      Hi Ajay,

      Just to clarify – is this for banner impressions on your site or on 3rd party(publisher’s) site? You can only track impressions on the site that you control or can install GTM code on.

  5. Josef Hilbert 2017-04-02 at 14:48 - Reply

    Hi, great post, I got 2 questions:
    1) eventCallBack
    The Custom HTML to track promotion clicks does not use the eventCallBack data layer variable as described in the sample code provided by google here …
    Was this done on purpose? In case you recommend to use the eventCallBack, shouldn’t we also consider Simo’s tip and use the eventTimeout as well?

    2) Tag Sequence
    Wouldn’t it be necessary to define a tag sequence so that the tag to track promotion impressions and clicks fires after the Custom HTML tags?


    • Max Bondarenko 2017-04-03 at 08:04 - Reply

      Hello Joseph,
      1) Our code is not blocking navigation nor the instructions above suggest using “Wait for tags” option in click triggers, so there is no need to add eventCallBack to dataLayer.push inside the code. However, if you modify the code above to block navigation (perhaps to make sure you capture all the clicks possible) until data is sent to GA do ensure to include both eventCallBack and eventTimeout.
      2) In terms of tag sequencing, it might not be the best way to do this as this may cause the tracking script to load several times and create conflicts/send duplicate data. The setup in the instructions loads the script that checks the page for impressions and then sends data to Data Layer if anything is found and triggers GTM event at the time, based on that fact we then send impression data to GA(using Internal Promotions View trigger). Our click tracking works in the similar way so there is no need for sequencing. You can potentially optimize the click trigger by moving logic from HTML tag for click tracking into a custom JS variable and then using it in your click trigger(thus removing extra step).

  6. Sam 2017-04-20 at 14:52 - Reply


    The issue I see at the moment with this, is that if no promotion is clicked on, Google will credit Transactions to the last ‘viewed’ promotion.

    However, if we are tagging a bunch of elements on our homepage as internal promotions, this attribution method will ruin transactional data – we definitely want this, as CTR could be misleading, versus whether the promo/site element really does lead to more orders. Any way around this??

    • Marc Soares 2017-04-25 at 11:11 - Reply

      Hi Sam,

      It sounds like you are concerned about the scenario where multiple promotions may be seen, but only the last one sent receives credit. This is how Google Analytics handles attribution for internal promotions, so there’s no way to circumvent it. It may help to label and track only your most important promotions, which would reduce the amount of “noise” in the data. This could provide a balance between tracking multiple promotions and having reliable attribution.

      It would likely be useful to have an “internal promotions path” report that could show you all promotions viewed and clicked in sequence before completing a transaction; something like the multi-channel path report. This isn’t possible within GA, but it could be built as a custom external report using the hit data that GA captures.

      We would be happy to discuss your particular situation with you offline. If you give us permission to contact you via email, we’ll get in touch with you directly.


  7. Nikhil Gupta 2017-06-16 at 00:17 - Reply

    Hi Max,

    Awesome post. Thanks a lot for writing this.
    One question – I want to treat my internal campaign as one would treat their external campaign.
    For example, if there is a campaign on an external site, a user lands on my site from that external site by clicking a link on the external site, the campaign source/medium are set according to that referral. If the user does not convert in that session, but converts sometime later (say from a new direct session, 2 days after), then also the conversion would be attributed to that source/medium as per the last referral.
    By using the method mentioned in this post, would I be able to treat my internal campaign the same way?

    Any thoughts, or alternative method would be greatly appreciated.


    • Max Bondarenko 2017-06-16 at 08:55 - Reply

      Hello Nikhil,

      You can adjust the promo click event to capture values for campaign/source/medium via “Fields to set” advanced tag option.

      However, we at ClickInsight would strongly advise against setting campaign/source/medium for internal campaigns as this makes attribution analysis a nightmare. We have seen multiple companies trying to dig themselves out of this hole and it is a struggle. The intent of campaign/source/medium parameters is to capture information about external sources as they usually the ones that bring traffic to your site and cost you money and significant effort. Resting these(and this is what would effectively happen if you set campaign/source/medium fields to values from your promos) could make your external marketing efforts appear useless as all (or most) conversions will be assigned to internal promos. You can use MCF reports to potentially mitigate some of the issues with this method – but that might be challenging as you will have to figure out a different attribution model for your analysis.

      In the end decision is yours, but do consider using custom segments instead of setting campaign/source/medium fields on click.


  8. Sushrut Vyas 2017-07-03 at 09:27 - Reply

    Hi Guys,

    For some reason the tags are not firing on Unit Links on my website. On other hand, when I’m clicking on other ads the tag is firing. Could You Please suggest something? I want to track the sponsored Unit Links clicks on my website.

    • Max Bondarenko 2017-07-17 at 08:59 - Reply

      Hi Sushrut,

      Do you have promo_name parameter on the “Unit links”? Also, double check for any typos.


      • Sushrut Vyas 2017-07-20 at 09:11 - Reply

        Hi Max,

        From what I’ve figured out, the tag is not firing for all the Google sponsored ads since the ads are in Iframe is what I’ve read. Could you please suggest a way out. The tag just wont fire for the Google sponsored promotions esp the Unit Links which redirect you to another URL.

        • Max Bondarenko 2017-07-20 at 09:17 - Reply

          Hi Sushrut,

          In that case you might consider adjusting your click tracking to “Any Clicks” from “Just Links” and add data attributes to elements containing iframes or ifrsmse themselves. via a custom scripts.

  9. Kristin Gillern 2017-07-19 at 16:36 - Reply

    Your screen shot for the “Click – Promo Click -ID Found” trigger is different than what I am experiencing. Tag Manager is requiring another entry after RegEx (ignore case). In the case of “Promo ID” would I add the variable promo_id? I thought this was already identified by selecting Promo ID.

    • Max Bondarenko 2017-07-20 at 09:11 - Reply

      Hello Kristin,

      Probably the screenshot is not very clear but the value of that field should be set to .+

  10. Andriy Verbickiy 2017-12-14 at 12:55 - Reply

    Hello, from Ukraine Max Bondarenko.Thanks for the work you’ve done!
    But is this manual still actual?
    I can not find marketing panel in E-commerce, may be google simpled it?

    • Marc Soares 2017-12-14 at 14:04 - Reply

      Hi Andriy,

      Looks like you haven’t enabled “Enhanced” Ecommerce reporting in your Google Analytics view. You should follow the instructions in Step 1 above to enable Enhanced Ecommerce. You will then see the Marketing section and Internal Promotions reports.


  11. emil 2018-01-02 at 13:47 - Reply

    Slick! I have to test this implementation. Going through the instructions:

    1. In the second custom html tag. You wrote “This tag should fire on the “Click – Promo Click – ID found” and “Click – Promo Click – Name found” triggers” ..doesn’t it add a “or” condition when you select two triggers? is this fine?

    2. Do you see any problems to setup if the site is already using enhanced ecommerce using datalayer?

    • Marc Soares 2018-01-04 at 09:56 - Reply

      Hi Emil,

      1. Yes, it is intended to be an OR condition. This means that you could use Promo ID or Promo Name or both to label your promotions. GA requires at least one of ID or Name to be set for each promotion.

      2. There shouldn’t be any issues implementing internal promotion tracking on a site that is already using enhanced ecommerce. In this case, Step 1 (enabling enhanced ecommerce in GA) is likely already done.

      Hope that helps!


  12. emil 2018-01-08 at 05:44 - Reply

    Thanks! Do you see any problem using this for House ads reserved via DFP? The link parameters are visible but the link itself will have a target _blank? The code looks like this

    Im also wondering if I need to make changes to the variables.

    • Marc Soares 2018-01-09 at 11:27 - Reply

      Hi Emil,

      In theory, this general approach will still work. However, it looks like the promo parameters are encoded in the URL, so using auto-event variables with Element URL / Query won’t work. GTM won’t be able to retrieve the parameter values since they are actually embedded with the “adurl” parameter. You would have to use custom JavaScript variables to parse the appropriate parameter values out of the URL for Promo Name, ID, Creative, and Position. Otherwise, everything else should work the same way.


  13. Firman Nugraha 2018-02-01 at 04:44 - Reply

    Great article, just what I need. One problem though, how can this be implemented for AMP pages? I found out AMP version of Google Tag Manager has fewer features compared to normal web page.

    • Marc Soares 2018-02-06 at 12:38 - Reply

      Hi Firman,

      Thanks for the comment. In GTM for AMP, you cannot deploy Custom HTML tags. However, there is a Visibility trigger that you could use to replicate the functionality of identifying impressions of internal promotion elements. In fact, even in a regular web container, you may wish to use the Element Visibility triggers. This post was published before built-in visibility triggers were available in GTM.


  14. Joel 2018-02-09 at 14:44 - Reply

    Fascinating read! I am confused between points 2 and 3.

    Is tagging the links with params like ?promo_name=any-promo&promo_id=123 etc. not enough to pass the data to GA, just like we use utm params for external campagns?
    Why and when do you need the whole GTM setup as detailed in point 3?


    • Marc Soares 2018-02-12 at 09:46 - Reply

      Hi Joel,

      Thanks for the comment. The full setup is required in order to populate the Internal Promotions reports in Google Analytics. If you only tag the links with “promo” parameters, you will end up seeing these in your Pages reports when someone clicks a link, but it won’t enable the Internal Promotions reporting capability of GA. By completing the full setup, you will be able to report on both impressions and clicks of your promotional elements.

      Hope that helps!

  15. Cori 2018-02-13 at 17:49 - Reply

    Hi Marc,

    I have a slider with 3 contents, these three contents link to: a search result page with a product list, a product page and a category page with a product list.
    How can I track a flow that start from one of the three contents? At the end, I want to know which content has more clicks.
    The whole slider has the attribute list name as ‘content recommendation widget’, but I don’t know how to split in each content.
    Thank you.

    • Marc Soares 2018-02-20 at 09:34 - Reply

      Hi Cori,

      You will need to label each of the 3 links in order to differentiate the clicks. If you are able to append query parameters to the links, you can follow the directions in Step 2 above.

      If you cannot append parameters to the links, you would have to use some other attribute or the href of the link in order to differentiate which one was clicked.


  16. Eric 2018-05-16 at 03:10 - Reply

    I got false warning at the tag 2.
    var promo_name = {{Promo Name}};
    var promo_id = {{Promo ID}};
    var promo_creative={{Promo Creative}};
    var promo_position={{Promo Position}};

    When I change them like the tag 1, it will be all right. Like so:
    var promo_name=’promo_name’;
    var promo_id=’promo_id’;
    var promo_creative=’promo_creative’;
    var promo_position=’promo_position’;

    Also there is a “;” after promo_id missed.

    • Marc Soares 2018-05-16 at 09:29 - Reply

      Hi Eric,

      Did you create the {{Promo Name}}, {{Promo ID}}, {{Promo Creative}}, and {{Promo Position}} variables as described at the beginning of Step 3? If you reference a variable that does not exist, GTM will throw an error when it validates your code.


    • Eric 2018-05-16 at 09:46 - Reply

      oh really. I used parameter “promo_name” as the varaible name. Sorry

      • Marc Soares 2018-05-22 at 17:52 - Reply

        No worries. We’ve also fixed the missing semicolon. Thanks for pointing it out.

  17. Dmitry 2018-05-20 at 18:33 - Reply

    In “Custom HTML tag to track promotion views. This tag should fire on the “DOM Ready” trigger and it will contain the following code” you missed a semicolon in var promo_id=’promo_id’//change to your query parameter if needed

    Should be var promo_id=’promo_id’;//change to your query parameter if needed

    • Marc Soares 2018-05-22 at 17:51 - Reply

      Hi Dimitry. Thanks for noticing the omission in the code. It has been fixed!

  18. Anthony 2018-09-12 at 13:07 - Reply

    Very informative post, super useful! I’m working to troubleshoot my implementation of it. My GA is showing internal campaigns views, but not clicks. Any suggestions would be appreciated. I’ve combed through your screenshots, and everything matches.

    • Heather Murphy 2018-09-14 at 10:23 - Reply

      Hi Anthony,

      Glad you found the post useful! Is it possible that there is a typo in the scripts, or an error in the GTM configuration?



  19. Claire S 2019-11-18 at 18:30 - Reply

    Hi, I know I’m a little late to the party, but I’m having trouble with this. I’m not getting any data in GA after following the steps, so I’m trying to figure out what’s happening. In GTM Preview mode, I can see that Promotion View is firing on DOM Ready, and the GA Tag is firing on promotionView. After Promotion View fires, the data layer values are as such:

    event: ‘promotionView’,
    ecommerce: {promoView: {promotions: [{name: ‘estie_lilac’, position: ‘headline’}]}},
    gtm.uniqueEventId: 14

    So the data layer is capturing the name and position (which are the only variables I used in my link), but when I go to the variables tab of the GTM preview pane, each of the custom variables says “undefined” for the return type and the value. Where’s the missing piece? Thank you!

    • Marc Soares 2019-11-20 at 17:32 - Reply

      Hi Claire,

      Your ecommerce variable in the data layer looks correct. Do you see the internal promotion dimensions being sent in the GA event? You can inspect the GA hit in your browser using the developer console or an extension like Omnibug ( If you see the promotion data in the event hit, then the issue is likely in your configuration or filters in GA.

      The custom Auto-Event variables will only be populated on the promotion click event. So, it’s fine that these are undefined on the promotion view.

      Hope that helps you further debug the issue.


  20. kian 2020-01-12 at 09:50 - Reply

    hi, I have a problem with my own website.
    we have so many sliders and banners on own website, and they change every week or even day.
    So for tracking them should I change tag or trigger setups? or once setup for the whole time?
    how can trigger read promo name automatically?

    • Marc Soares 2020-01-20 at 12:06 - Reply

      Hi Kian,

      In order to use this method for internal promotion tracking, you will need to have a way to tag each different banner or slider with unique parameter values. You may need to incorporate this into the process for updating the promos, or you could find a way to dynamically populate the promo_name and other parameters from fields in your content management system.

      As long as you have the promo_name, promo_id, promo_creative, and promo_position on all your banners, you won’t need to update the tracking setup in GTM.


  21. Lucas Schultze 2020-06-04 at 14:22 - Reply

    Any concerns on these URL’s being indexed? If served by Google or copied elsewhere it could inflate your tracking. Probably better off using data attributes on the elements if you have access to that level of the code.

  22. Lavina Yuan 2020-08-24 at 19:03 - Reply

    Hi, I have a question – the website has a carousel that contains 3 banners. We do have promo_id, promo_name, promo_creative, and promo_position for the 3 banners, but somehow the promo_id is kept the same for the 3 banners, which I don’t get it. Shouldn’t promo_id be different since it’s an id? I was told the 3 banners get tracked separately. How come? If the whole carousel gets tracked, I understand because the id is the same for the 3 banners. But how come the 3 banners get tracked separately with the same id (though promo_name, promo_creative, and promo_position are different)?

    • Marc Soares 2020-09-09 at 10:55 - Reply

      Hi Lavina,

      Although it is named “ID”, the Promotion ID dimension in GA doesn’t really have any special meaning in how the data is collected and processed. You can think of the ID, Name, Creative, and Position as four available dimensions that you can use however you want.

      If your 3 banners have the same Promo ID, each will still get tracked as an impression or click. However, in the Internal Promotion reports in GA, you won’t be able to distinguish the 3 banners based on the Promo ID alone. You will need to use the name, creative, or position as a secondary dimension.

      In general, we do suggest using the Promo ID dimension to uniquely identify each promotion. However, this is a design choice and not a requirement of GA.


      • Lavina Yuan 2020-09-09 at 12:32 - Reply

        Thanks very much Marc for your clear explanation. Have a great day! 🙂


  23. Túlio 2021-10-27 at 08:07 - Reply

    First of all, congrats to this amazing article. I hope I’m not too late for the party.

    I have had implemented a couple days ago, and I noticed that is not tracking any click, even the tag firing when I run the debugger (GTM). Also I noticed, that the impressions doesn’t not goes to Google Analytics fast, it take some time right?

    And last but not least, with this approach can we measure how much revenue a banner promo did with their products? Or if I click in multiple banners, will Analytics attribute to last banner? How do I know the revenue by banner (my home has 6 banners)

    • Hayley Yacynuk 2021-11-05 at 09:17 - Reply


      In terms of troubleshooting your tags not firing, I have linked this Google Tag Setup Support document. Take a look to see if any of the solutions apply for your particular situation. If these still do not help, I recommend retracing the steps in the blog post to see if anything was missed.

      As for your next question, yes if you just switched-on tracking with analytics, impressions can take up to 24hrs to be reflected in GA.

      And last but not least, if a session includes multiple internal-promotion clicks, then the last-clicked internal-promotion is credited for the transaction. Google has provided an article explaining the process in more depth which can be found here: Enhanced Ecommerce: Internal Promotion.

      I hope this helps answer your questions!

  24. Tevadar 2022-04-20 at 19:26 - Reply

    Hello, this is exactly what I was looking for. Unfortunately it isn’t quite working. It’s firing all of the data into the variable name I used in GTM Slightly altered to (HF_promo_name, HF_promo_position, etc.) It’s not tracking views either, just clicks.

    I’m sure it might be something I missed along the way but I looked over all the steps 3 times and everything looks fine.

    • Hayley Yacynuk 2022-04-25 at 13:08 - Reply

      Hi Tevadar,

      Thanks for your question! We’re happy to hear you enjoyed our post.

      Just to confirm, when you changed the name of the query parameter values (HF_promo_name etc), did you also alter the query parameters in the promotion views custom HTML tag to match the names you configured?

      If not, you will need to go back and change any lines of code that look like var promo_name=’promo_name’; to var promo_name=’HF_promo_name’;

      If you would like further clarification or guidance, feel free to contact us and we can work on it together!

      • Tevadar 2022-04-27 at 14:46 - Reply

        I actually went back in and changed the variable names to the same ones you used in the example. Now I get the page view data but not the click data.

        How come you refer to the variable name in one script and the variable index in the other?

        Dom Ready
        var promo_name=’promo_name’;//change to your query parameter if needed
        var promo_id=’promo_id’;//change to your query parameter if needed
        var promo_creative=’promo_creative’;//change to your query parameter if needed
        var promo_position=’promo_position’;//change to your query parameter if needed

        Promo Click
        var promo_name = {{Promo Name}};
        var promo_id = {{Promo ID}};
        var promo_creative={{Promo Creative}};
        var promo_position={{Promo Position}};

Leave A Comment