Sequence segments in Google Analytics

With segments in Analytics, we can analyze a certain group of users on our website. Segments can help us to get conclusions which we can show to our client in order to help them to make better business decisions.

Google Analytics has some predefined segments, for example:

  • Bounced Sessions
  • Mobile Traffic
  • New Users
  • Non-Converters etc.

If we can’t extract a group of users with predefined segments, Analytics has an option to create custom segments. Custom segments give us the ability to group users based on our needs and to analyze their behavior on our website.

But, before you start creating custom segments, it is important to know the difference between User, Session and Hit scopes.

Which scope should I use? Depending what you want to analyze, you will use a different scope in the segment:

  1. User segments – we use them when we want to analyze the behavior of our users on the website (for example, how many users created $5.000 revenue across all their transactions in certain period)
  2. Session segments – they come in handy when we want to analyze certain traffic source or to see what happens inside sessions (for example: what users from newsletter campaign do on our website )
  3. Sequence segments – we use them exclusively when we want to segment users who done something in particular order, when we want smoother segmentation of users behavior (for example: how many users went straight from homepage to contact page)

Let say, we define segment with User scope, where user visited the category /Office and added product to cart:


Let’s take an example where we have three users who visited our website. With user scope segment, we will include all three users. The first user in his first session added the product to cart on category /Electronics, while in his second session he visited the category /Office. Although these two activities happen in different sessions (visits), this user will be included in our segment.

The second user who visited category /Electronics in his third session added the product to cart and after that visited the category /Office, will also be included in our segment.

The third user, who in his second session visited the category /Office and added the product to cart will be also included in our segment.


What will happen if we create session scope segment with the same conditions?


Session scope segment will include only second and third users because these two activities happen inside the same session (visit):


Sequence segments allow us more precise segmentation if we want to follow a particular order of activities that users made on our website.

In our previous example, when we created session scope segment, we included only last two users with our segment. If we take a better look, the second user visited the category/Electronics, added product to cart and after that visited the category /Office, where he didn’t add the product to cart.

If we want to segment only users who were on category /Office and added products to cart from /Office category, then we will create sequence segments where we define two steps.


In the first step we define hit (interaction) in which we want to include only users who visited the category /Office. And in the second step, we define hit where we want to include only users who also added the product to cart.

But, between steps you have two options:

  • is immediately followed by – means the user visits the category /Office and then the next thing he does is add the product to cart
  • is followed by – means the user visits category /Office and then at any point later in the same session (visit) they add the product to cart

Since we chose is immediately followed by we can be pretty sure that user added to cart one of products from /Office category.

With this segment, we will include only third user, for which we can be sure that he added the product to cart from category /Office:


To conclude, if we use User scope segments, conditions that we define in our segment can happen across multiple sessions (visits). If we use Session scope segments, then conditions must happen inside the same session (but without any particular order).

With sequence segments, we define the order of hits (interactions) that user made, which allows us more precise segmentation. It is important to understand scope in segments because otherwise, we can read the data on a completely wrong way.

When creating sequence segments you can set up to 10 steps, and inside one segments you can combine more sequences.

Solving Attribution with GA Measurement Protocol Payload Widening


For starters let’s have Google explain what Measurement Protocol actually is and when it makes sense to use it (explained by Justin Cutroni):

As the documentation states Measurement protocol is used for this purpose:

  • Measure user activity in new environments.
  • Tie online to offline behavior.
  • Send data from both the client and server.

You can even find some of the basic hit payload examples in the dev docs here These hits will be valid yet if sent as is it is a question how valuable the data will be perceived once in reports. A suggestion would be to widen. Always. Making the hit valid and valuable at the same time.

The issues with MP can best be explained by using a simple example such as:

Company A sells product B in multiple countries. The process contains multiple steps. 1st step where a user visits the site and fills in and successfully submits a lead form. After validation and internal risk check  we enter 2nd step where the initial transaction is processed. Delay between step 1 and 2 can be up to 14 days. 3rd step – a user can have a recurring payment contract which automates billing process each 30 days – there is no need for the end user to visit the site in order to confirm.

Scenario – Sending a valid hit with bare essentials in step 2 and 3 results in:

Device, Geo and traffic attribution will be or can easily be skewed. For instance sending a minimum valid hit will basically send information which will be generically attributed to the IP of the server sending the hit (messes up geo attribution), device sending the hit (messes up device attribution), and traffic defaults to direct (which is in some cases fine as GA uses last non direct traffic source attribution meaning IF any campaign exists prior to the MP hit tied to a specific Client Id within the Campaign Timeout window (6 months by default) the direct traffic will just be overridden).

One additional thing which may happen if scenario follows this path:

  1. step 1 form submit via google / cpc
  2. between step 1 and step 2 an additional session / visit happens via google / organic
  3. step 2 sends the transaction to GA yet the transaction will be attributed to google / organic – so it is a question which of the sources you want the transaction to be tied with – cpc or organic?
  4. subsequently recurring transaction attribution for step 3 will always subscribe to the latest known campaign and not the initial source of Lead or Transaction

In order to prevent this from happening there are some additional parameters which you should:

  1. store (in your internal system for processes such as lead form submits) and
  2. send with the measurement protocol hit

Parameters for widening the MP hit (solving attribution)

dl – document location
Circumvent any hostname filtering (dp and dh parameters as options to this)

uip – user IP
Preserve location

ua – User agent
Preserve info on user agent (optional)

ds – Data source
Segment on data source. (cdN (custom dimension) as option)

cn/cm/cs/gclid/dclid/dr – traffic – campaigns from UTM / Adwords or DC / document referrer / (none if no info exists or create a virtual direct?)
Preserve traffic – partially. The issue is to preserve attribution for the traffic source which generated the sales – if no info would be provided some mid newsletter driven session may miss attribute results.

Sending the Measurement protocol hit

Prior to pushing all your work to production you should definitely test the setup and outcomes using and a dummy Google Analytics property.  In most cases you will send the hits as events, non interaction ones so make sure ni parameter is set to 1. This may challenge the way you see the standard reports as if you send a non interaction hit something unexpected will happen – no session will be created but there will be a user reported for the period in question – the attribution will stay intact though.  MCF reports will attribute and report as expected.

I would really be interested to know which other parameter you find essential or some of your MP cases where the valid hit is just not enough – Happy tracking!

Logging Oversized Enhanced ecommerce Google Analytics hits in Google Sheets


If you ever worked on a Enhanced Ecommerce implementation project there is a chance you encountered the ‘Payload size is too large (15226).  Max allowed is 8192.’ message which actually means there will be nothing stored in reports. There are some workarounds for this particular issue such as:

In this post I’ll only focus on explaining how to determine the EE actions and hits the payload may be considered an Issue.

Step 1 – Google Sheets setup

The Sheets procedure and the entire script which reports on the questionable hits can be found here – (by Martin Hawksey). Follow the entire procedure and do not forget to publish and update the Script once you made the necessary changes!

A quick note on the Google Sheet itself. This one needs to be filled with header row so that we can map our payload to Google Sheets as in this example:


Just the header (1st) Row. The column entries are case sensitive so whatever you define in the payload sent to Google Sheets needs to exact match! For my example I used these column labels (you may notice a ‘slight’ resemblance to Measurement protocol parameters):

  • timestamp
  • payLoadLength
  • tid (tracking id)
  • cid (client id)
  • uid (user id)
  • t (type of hit)
  • pa (product action)
  • ni (non interaction)
  • dl (document location)
  • dp (document path)
  • dt (document title)
  • ec (event category)
  • ea (event action)
  • el (event label)
  • ti (transaction id)
  • tr (transaction revenue)

Make sure that the cid and ti columns are formatted as Plain Text otherwise some unwanted auto formatting may occur. Additional parameters may be added as needed.


Step 2 – Google Tag Manager Setup (Mimic the Google Analytics payload)

When proceeding with this it would be prudent to create an additional GA tag in GTM leading to a dummy GA property just to be sure nothing goes wrong with the data. Basically add a new field to set to each GA tag which passes on EE payload as in the following example:


So I will use the sendHitTask as means to read the entire payload and send it to Google Sheets once the payload exceeds a certain length. The sendHitTask field will use a Custom JS variable (Code below – based on this post) which returns a function which is designed (apologies for the sucky code) to push the default payload to GA and further on send the custom payload to Google Sheets – :

function sendHitTask(){
  return function(model) {
    var payLoad = model.get('hitPayload');                     
    var trackingBaseUrls = ['', ''];

    for (i = 0; i < trackingBaseUrls.length; i++) { var baseUrl = trackingBaseUrls[i]; if (trackingBaseUrls[i].indexOf('collect') > -1) {
          var req = new XMLHttpRequest();
'POST', baseUrl, true);
      } else if (payLoad.length > 7000){
        var payLoadExtract = payLoad.split('&');
        var payLoadArray = {};
        // Push values to array for later access
          for (i = 0; i < payLoadExtract.length; i++){
                  var splitArray = payLoadExtract[i].split('=');
                  payLoadArray[splitArray[0].trim()] = splitArray[1].trim();
            // Specify values to be sent to Google Sheets from array
            var tid = 'tid=' + payLoadArray.tid,
            cid = '&cid=' + payLoadArray.cid,
            uid = '&uid=' + payLoadArray.uid,
            t = '&t=' + payLoadArray.t,  
            pa = '&pa=' +,
            ni = '&ni=' +,
            dl = '&dl=' + payLoadArray.dl,
            dp = '&dp=' + payLoadArray.dp,
            dt = '&dt=' + payLoadArray.dt,                                      
            ec = '&ec=' +,                                      
            ea = '&ea=' + payLoadArray.ea,                                      
            el = '&el=' + payLoadArray.el,                                      
            ti = '&ti=' + payLoadArray.ti,                                      
            tr = '&tr=' +,                                      
            timestamp = '&timestamp=' + {{UTIL - Date}},
            payLoadLength = '&payLoadLength=' + payLoad.length;
            var collectPayLoad = tid + cid + uid + t + pa + ni + dl + dp + dt + ec + ea + el + ti + tr + timestamp + payLoadLength;
        // Send Values to Google Sheets
        var collectUrl = baseUrl +'?'+ collectPayLoad;
        var myImage = new Image();
        myImage.src = collectUrl;

And this is basically it. Whenever this tag is triggered it will push data to GA but if the payload exceeds the defined condition it will log it in the Google Sheet which will hopefully help you in debugging the implementation.

DataStudio how to Report Google Analytics MCF and Standard Ecommerce data from Google Sheets


How to use DataStudio in order to report on Average Days to Purchase or Average Touchpoints to purchase a specific product or category of products based on data collected in Google Analytics? Easy! For the entire setup you only need to have / do:

  1. Have access to a Google Analytics property with Ecommerce implemented
  2. Have access to DataStudio
  3. Read one of the previous articles on how to join MCF report data and Standard report data in Google Sheets

Google Sheets as Data Source

Google Sheets GA plugin extension set and queries prepared as in example:


Reporting Sheet where you do all the join operations:


Once this is set proceed to adding a Data Source inside Data Studio (Google Sheets as Data source):


Select the appropriate file and Sheet (the reporting one) and proceed in adapting the source by formatting the fields as in example:


Note that we only had to edit Aggregation settings to Average and created an additional Calculated Field Metric which basically Averages the Transaction Value based on the Count of Transactions Ids – Formula: Total Conversion Value (MCF) / COUNT(Transaction Id (MCF)).  Proceed to add any desired visualization to the report page – in this example I used Scatter Chart and Simple Scorecard. For example the Scatter Chart uses a simple setup as follows:


The final result was a simple one page dashboard:


The point of the exercise should be to easily push data to DataStudio (from any available source – even ‘offline’) in order to quite simply explore the data and relations of 2 or more variables – who knows something interesting may pop up:)



Standard vs. Dynamic remarketing

In Google AdWords, remarketing option is available for years. Remarketing helps us reach people who visited your website. Previous visitors can see your ads while surfing the internet (Google Display Network) or while searching on Google (Google Search Network).

With dynamic remarketing, you can serve the ads to previous visitors, but the ads are showing products which those visitors have viewed during their visit.  Dynamic remarketing is available only for Display network.

To start with dynamic remarketing, you need to:

  • create product feed (.csv, .tsv, .xls, .xlsx) – in the feed you need to enter products or services that you want to show to the user. You can enter only certain product category, not all your products (for example, only laptops)
  • set up the remarketing tag with custom parameters – the remarketing tag set/collects a cookie and passes dynamic parameters to Google servers
  • dynamic display ads – create display ads that will show your products

Compared to standard, dynamic remarketing requires a little more technical work for your website developers, in order to everything works properly.

Also, it is important to note that the data in the product feed needs to change every time when a change occurs on the website. If product prices change every week, it is good to update the feed too. Otherwise, the user can see wrong data (wrong price, model etc.) in your dynamic ads or land on a 404 page.

After set up, AdWords will automatically create 6 remarketing lists that we can use for targeting.


  • All visitors – all users who visited your website
  • Conversion abandoners – users who entered the shopping cart, but didn’t buy the product
  • General visitors – for example, users who saw product categories
  • Past converters -users who made a purchase
  • Product or service -users who saw a particular product i.e., visited the page of particular product
  • Searchers – users who used search engine on the website

But how dynamic remarketing works? User visits your website that contains remarketing code with custom parameters. Remarketing code collects all parameters and passes to Google servers. Google collects cookie ID and parameters (page type, total value, etc.).  Google uses item IDs from cookie (IDs of products that user viewed on your website) and connects with ID in the feed in order to know which products should be displayed in the ad. While surfing the internet, user will see dynamic ads that contain products that he viewed on the website along with product information (picture, name, price etc.). You can customize the ads, for example insert company logo, change background color etc.



Why use dynamic remarketing?

Compared to the standard, dynamic remarketing gives you the ability to better personalize the ads that are served to the user. The disadvantage is that the dynamic remarketing is a little bit more technical demanding to implement. Dynamic remarketing usually shows better results compared to the standard remarketing campaigns. But, to be sure, we suggest to test and compare the results.:)

DataStudio how to create a Google Analytics Custom Channel Grouping

Google DataStudio is an excellent addition to the Google Suite tool arsenal which deals with the reporting / exploration part.  A much more complex system than what we are used to with Google Analytics Dashboards yet still really easy to use! The product is still in Beta but looks very promising.

For more information about DataStudio here are some useful links to get you up and running:

  1. Product overview –
  2. Help center –
  3. Creating a report (case) –

Back to the issue at hand:

How to create a Google Analytics Custom channel grouping inside DataStudio

Most of avid Google Analytics users are really keen on redefining the default channel grouping or adding custom channel grouping to have a better understanding of how ‘channels’ perform on a high / low detail level. Unfortunately GA Reporting API / Core API still does not have such a dimension exposed / available so in our reporting and analysis effort we have to resort to recreating the conditions with filtering. Same process has to be applied when reporting in DataStudio. So, whenever you want to widen the Default channel grouping by creating a Custom Channel grouping inside GA and want this to be accessible via DataStudio you need to do this:

  1. Add a data source – Google Analytics – procedure described in links above
  2. Add a custom field to the data source – which I will describe next

To begin with here is the official support for calculated fields –

Step 1
Create the field
04 datastudio create a calculated field


Step 2
The formula

07 datastudio building blocks


This is the tricky part. You need to mimic the order and definitions as you would in the GA Admin interface using prebuild DataStudio functions (  The basis will be the function CASE ( which uses this simple syntax:


This will translate to:

WHEN our source or campaign matches ‘some string’ THEN the dimension output will be ‘desired channel grouping dimension value’
ELSE if we missed to group some traffic inside a group it will output ‘You missed this’

The best way to proceed is to open Notepad or similar text editor and do it there as DataStudio formula entry has auto fill feature and you can only write in a single line so it will eventually strat to be extremely hard to track what is defined or what needs to be corrected.

‘Referral’ channel group
WHEN Default Channel Grouping = “Referral” THEN “Referral”

‘Paid listings’ channel group
REGEXP_MATCH(Medium, “.*(listing|xyz).*”) AND REGEXP_MATCH(Source, “.*(tripadvisor|abc).*”) THEN “Paid Listings”
In this case we are using REGEXP_MATCH function where we evaluate Medium AND Source for phrases we use when creating Custom Channel Grouping in Google Analytics.  We can also use other logical operators to create a more complex condition. Please note that REGEX we are used to in Google Analytics does not behave the same as in DataStudio (after some tinkering guys from confirmed it – thanks!)  – more on DS regex –

Your end result should have the following structure:

WHEN Default Channel Grouping = “Referral” THEN “Referral”
WHEN Default Channel Grouping = “Direct”  THEN “Direct”
WHEN Medium = “cpc” AND REGEXP_MATCH(Campaign, “.*(brand|bcmp).*”) THEN “Paid Brand Campaign”
WHEN REGEXP_MATCH(Medium, “.*(listing|xyz).*”) AND REGEXP_MATCH(Source, “.*(tripadvisor|abc).*”) THEN “Paid Listings”
… add more definitions as you see fit
ELSE “Other”

Copy your entire code and paste it inside the formula field:

05 datastudio fill in the formula

Step 3
Update the data source

07 update data source



Step 4
Change the Dimension in your widget from Default Channel grouping to your Custom Channel grouping one.

Click on the current dimensions.
09 choose the calculated field

Choose the newly created one.

10 My custom channel grouping

A small hint – add a secondary dimensions – Source / Medium just to check if all the traffic is indeed in predefined and expected channel group.

11 make sure it is applied

Step 5
Refresh the data

12 refresh the data


Final notes:

  • Any change you do inside GA should be redone inside DataStudio Custom field (at least till GA surfaces some kind of a custom channel grouping dimension via API)
  • The same approach can be used for any kind of filtering / segmentation and once you get used to the syntax it is pretty useful and offers nice customization options