Reporting on GA4 Landing Pages in Looker Studio

The Landing Page report in Universal Analytics was on many people’s short list of favorites. If you are one of those people, the Landing page report in GA4 is likely a bit of a disappointment. For many of the GA4 properties I’ve worked on, the first row in the report is (not set), and for some the majority of conversions show up in that row. What gives?

In this post, we’ll make improvements to the standard report, explore what causes the (not set) issue, and discuss a few mitigation strategies. Then we’ll create a custom First user landing page dimension that you can use to understand what content is attracting new users to your site and whether or not they come back and convert to customers or buyers.

There are two videos that accompany this post. The first, below, covers the standard GA4 Landing page dimension. The second describes how to create the custom First user landing page. That video is embedded further down the post.

Customizing the GA4 Landing page report

If you can’t find the standard Landing page report…

The landing page report can be found under Reports > Engagement in GA4. If you don’t find it there, you can add it by clicking on the library icon below the reporting navigation, then select ‘Edit collection’ to add it to a collection of reports. From there you can search for the report and add it to your navigation (Google help on how to do this).

Improving the report

The landing page report shows sessions, users, engagement, conversions and revenue tied to the page on which a user lands at the start of a session. There are a couple of metrics that can make the report a lot more useful:

  • Event count – when you add Event count as a metric, GA4 adds the ability to select specific events, similar to the Conversions column.
  • Session conversion rate – I like adding this to all of my session-scoped reports.

To add these columns, click on the pencil icon in the upper right – you need to have Editor or Administrator permissions to do this. I walk through detailed steps to add the columns in the video.

How Event count works with respect to landing pages

One thing to be aware of: since Landing page is a session-scoped dimension, the event counts you see in this report are per session, not per page view. This means that, for example, if a row shows 10 landing page sessions and 20 page_view events, on average people who land on that page go on to view one more page.

Google help page on the landing page report

Landing page (not set)

A common frustration with the Landing page report is that a lot of sessions are attributed to “(not set)”. What does this even mean? How can a user visit the site and not land on a page? I’ve looked into this a bit and found three common causes:

  1. Audience-triggered events – when you create an audience, you can select to trigger a custom event when a user is added to or refreshed in the audience. For example, you can create an audience of people who visit 5 or more pages and trigger a custom event. This is a useful tactic for recreating the engagement goal conversion types in Universal Analytics. Unfortunately, in my experience, 100% of audience-triggered events show up in the (not set) row. This also implies that these sessions are being double counted, since these users did have a landing page prior to triggering the event.
    How to mitigate: unfortunately, all you can do is cross your fingers and hope Google fixes this issue.
  2. Events sent by the Measurement Protocol – the Measurement Protocol is an API that you or third-party tools can use to send events to GA4. I’ve run into quite a few tools that use it, including for call tracking, donation tracking, event booking, form submit tracking and other purposes. When an event is sent via the measurement protocol, the sender includes a session ID, and may include a client and/or user ID, but these often don’t match the IDs GA4 has already created for the same user and session. In other words, a new user and session is created. And unless the sender includes a page_view event for the same session ID, the session that is created won’t have a landing page. 
    How to mitigate: it is possible to pass the GA4 client ID and session ID with a Measurement Protocol event, which will result in the event being associated with an existing session and the Landing page will be attributed correctly. This article describes how to configure these parameters in detail: Session Attribution with GA4 Measurement Protocol. If Measurement Protocol events are coming from a third party, you may need to do some dev work to pass them these values, and some persuasion work if their tool doesn’t currently support these parameters.
  3. What I call ‘sessions-not-sessions’. These are cases where a user is on the site, loads one or more pages, leaves the tab open, then comes back > 30 minutes later and closes the tab without doing anything else. This creates a session with two events: session_start and user_engagement. Since there is no page view in these cases, they also show up as (not set).  This seems like it might be an edge case, but it is actually very common. It varies by site, but for several that I’ve looked at, these account for 10-20% of total sessions.
    How to mitigate: you can increase the default session duration in GA4 to reduce the impact of this phenomenon. This article describes the issue in more detail and provides instructions on changing session duration: Landing page is (not set) in GA4.

The first two of these are especially problematic because they typically represent events that are flagged as conversions, meaning that a disproportionate number of conversions show up in the (not set) row. 

Reporting on landing pages in Looker Studio

In the video I re-create the Landing page report in Looker Studio, with a
 few enhancements:
  1. As of this writing, the Looker Studio GA4 connector does not inDialogue showing the Average engagement time per session formula: User engagement / sessionsclude an Average engagement time per session metric. To re-create this metric, add a custom field with the formula to the right. Make sure to change the type of the field to Numeric > Duration (sec.)
  2. Add a filter to exclude rows where ‘Landing page + query string’ is Equal to (not set)
  3. Add an Advanced filter control on the field Landing page + query string, so users can search for specific pages.

creating a user-scoped First user landing page dimension

To understand what content is attracting new users to your site and whether or not they come back in a different session and convert to customers or buyers, we’ll create a custom First user landing page dimension that can be used for reporting in Looker Studio.

Watch the video for a walkthrough of the steps described below.

1. create a custom html tag in google tag manager

If you’ve been doing any customization in GA4, you know that Google Tag Manager (GTM) is an essential part of your toolkit. We’ll use GTM to persist a user property that stores the page path on which the user first arrived at a site. The following code persists the user’s landing page path between visits. To implement it, copy the code into a new Custom HTML tag in GTM. Set the trigger to Page View > All Pages.

There are three functions in the code. 

  1. gtm_getCookie is a utility function that gets a user’s cookie based on the cookie name. 
  2. getOrgDomain gets the first portion of the URL that is specific to the web property, e.g. if the domain is shop.xyz.com, it returns xyz.com. It does this in order to prevent the script from setting a new landing page if the user moves from one subdomain to another. One thing to be aware of: if the GA4 property spans multiple domains, e.g. xyz.com and 123.com, the script will set a new landing page when a user changes domains. I haven’t come up with a great solution for this yet.
  3. The third is a self-executing function that stores a user’s landing page path in a cookie the first time it loads and pushes the path value to the dataLayer. On subsequent loads, it gets the stored page path value from the cookie and pushes that to the dataLayer.

If you are wondering why we are getting the user’s page path instead of the full landing page URL, the reason is because GA4 User Properties can’t be longer than 36 characters. Because of that, we need to economize on the number of characters we are pushing to the property.

    
     <script>
// this function returns a cookie based on the cookie's name
function gtm_getCookie(name) {
  var cookies = decodeURIComponent(document.cookie);
  var cookiesArray = cookies.split(';');
  var cookie = cookiesArray.find(function (item) {
    return name == item.trim().substring(0, name.length);
  });
  return cookie;
}
  
/*
* This function returns the organizational domain, e.g. the primary
* domain with subdomains stripped out. This function is used below - when the 
* cookie that stores the landing page is set to this domain so it doesn't
* get reset if a user moves from one subdomain to another.
*/
function getOrgDomain(){
  var i,h,
    org_domain_cookie='get_org_domain=cookie',
    hostname = document.location.hostname.split('.');
  for(i=hostname.length-1; i>=0; i--) {
    h = hostname.slice(i).join('.');
    document.cookie = org_domain_cookie + ';domain=.' + h + ';';
    if(document.cookie.indexOf(org_domain_cookie)>-1){
      // tries to set a cookie on 2nd-level domain, 3rd, etc - returns domain when it succeeds
      document.cookie = org_domain_cookie.split('=')[0] + '=;domain=.' + h + ';expires=Thu, 01 Jan 1970 00:00:01 GMT;';
      return h;
    }
  }
}

(function() {
  var domain = getOrgDomain();
  var urlCookie = gtm_getCookie("lp_path");
  // if no url cookie exists, create it and push url to datalayer
  if (!urlCookie) {
    var cookieExpiry = new Date();
    // Set expiry time of one year
    cookieExpiry.setFullYear(cookieExpiry.getFullYear() + 1);
    var expires = "expires=" + cookieExpiry.toUTCString();
    // user parameters are <= 36 characters, so we're not pushing the full URL
    dataLayer.push({"lp_path": {{Page Path}}});
    document.cookie = "lp_path" + "=" + {{Page Path}} + ";" + expires + ";path=/;domain=" + domain;
  } else {
    // if cookie exists, get the url from it and push to dataLayer
    var pathFromCookie = urlCookie.trim().slice(8) || null;
    dataLayer.push({"lp_path": pathFromCookie});
  }
})();
</script>

    
   

2. create a custom variable in gtm

The Data Layer Variable type in GTM gets a value from the dataLayer and makes it available to other tags. The script above pushes a ‘lp_path’ variable to the dataLayer. This turns it into a GTM variable.
GTM lp_path dataLayer variable

 

3. add a user property to the ga4 configuration tag

Modify your GA4 configuration tag in Google Tag Manager to include the following user property. Set the value of the property to the variable you just created. Note that double curly braces tell GTM to insert a dynamic GTM variable value.

I named the property ‘first_user_landing_page’ because GA4 prefixes various user-scoped dimensions with ‘First user’. For example, the ‘First user default channel grouping’ dimension indicates the channel a user came from the first time they visited a site.

first_user_landing_page user property

 

4. update the configuration tag trigger

At this point, you have everything you need in GTM, but there’s one problem: assuming your GA4 configuration tag is also triggered on Page View, the path variable you created won’t exist when the configuration tag fires. You can fix this by changing your configuration tag to fire on the DOM Ready trigger. If you do this, keep in mind that other GA4 tags inherit parameters set in the configuration tag, so you should update their triggers as well. Another way to accomplish the same result would be to configure tag sequencing to fire the Custom HTML tag before the configuration tag.

At this point you are done with the GTM portion of this process. Test your new tag, variable and configuration tag change in GTM preview mode and publish your changes if everything looks good.

5. add a ‘first user landing page’ custom dimension in ga4

In GA4, go to Admin > Custom definitions and add the following dimension.

Custom dimension dialogue box in GA4

6. refresh your ga4 connection in looker studio

You’ll need to wait at least a day for data to populate in GA4 before this step.

When ready, refresh your GA4 data source.

7. create a lookup table in a google sheet

I mentioned above that GA4 limits user properties to 36 characters. This is pretty annoying for our purposes, since page paths can often be longer than that. I fixed this in Looker Studio by creating a lookup table in a Google Sheet that cross-references truncated page paths with complete page paths. Below is an example of what this table looks like. I created the lookup column on the left with the Google Sheets LEFT formula, e.g. =LEFT(B2,26)

Screenshot of a Google Sheet with landing page lookups.

You’ll then need to create a new data source in Looker Studio to connect to your Sheet.

8. create a blend in looker studio to join to your lookups

We’re so close! The last step is to create a blend in Looker Studio from your GA4 data source and the lookup table to get the full LP path in your report. Below is how I have my blend set up, but feel free to pull in other metrics from your GA4 data source.

Also notice that I added a filter to my GA4 data source – the filter excludes null values from the blend. This is not absolutely necessary, but you will likely get some instances where your configuration tag fires and the custom HTML tag you created has not populated the path value.

One caution: make sure not to have any duplicate rows in the lookup sheet. Duplicate rows on the right side of your join will result in duplicate rows in the joined data, which will inflate your metrics.

image 4

Voilá, that’s it! You now have a blend you can use to report on First user landing page in Looker Studio!

beware of cardinality

Plus a few other gotchas.

Google's warning: "Creating a custom dimension with a high number of unique values may negatively impact your reports."

Google recommends that you avoid creating custom dimensions with “high-cardinality”. What this means specifically is that dimensions with more than 500 unique values may affect reporting performance, and will result in some of your landing pages being aggregated into an “other” row in reporting. So, if you have a lot more than 500 pages on your site that users are likely to land on, the technique I have described here may be of limited value.

A few more things to keep in mind:

  • GTM automatically applies consent settings to Google tags, but not custom HTML tags, so make sure you configure it appropriately according to your consent policy when you create the tag.
  • This process relies on a 1st-party cookie. As such, it will not persist a user’s landing page if the user is blocking 1st-party cookies.
  • The approach I described relies on a lookup existing in the lookup table – if your page paths change a lot, you may want to just report on the first 36 characters and call it good.
  • If your site requires URL parameters to identify unique pages, you’ll need to use the Page URL GTM variable instead of Page Path. You can remove the protocol and domain in the JavaScript function, but this still might not be enough to get below 36 characters.

If you’d like help with this or anything else to do with GA4 or Looker Studio, check out our marketing data analysis services.

Read more GA4 resources and tutorials.

Share This Post

Share This Post

Hunting for Bots

Bot traffic in GA4 is really frustrating. Our Head of Analytics Nico Brooks takes us through the arduous effort of identifying & excluding bot traffic.

➔ Read more

master GA4

with personalized training

A training program like no other. Work with expert marketers for 1:1 training to maximize learning & impact.

have you registered?

Our next free digital marketing seminar is coming soon!

[MEC id="946"]