How Do I Measure a Single Page Website That Uses URL Fragments with Tealium/GA? - google-analytics

I was asked to capture the analytics on a website. The website is made up of 5 web pages, but I now realize that the domain is the same and the only thing that changes is the URL fragment, i.e. www.domain.com#a, www.domain.com#b. The only info that comes through to GA is the domain and it does not include the URL fragments. The tracking code I'm using is Tealium and the data is being sent back to Google Analytics. How can I set this up so that i can see the entire URL in GA including the URL fragments?

So, from Tealium's perspective we need to trigger a view event when a new fragment is loaded (if I am understanding this correctly).
If we assume that the fragment change occurs on a link click then we need to trigger the view event when the link click occurs.
From the GA perspective, we need to trigger a view that captures the new information. For a view this is likely to be location, path and title.
Therefore, we need Tealium to construct the new data points and then pass them in a view event to GA.
The simplest way to do this in Tealium (all things being equal) is via a jQuery onHandler Extension
The jQuery extension requires the following information:
jQuery selector (or selectors) to pay attention to
"Trigger On" event type (this will be Click in this example)
Tracking event type to run (View event in this case)
Variable & values to set
Tealium jQuery onHandler extension config
note it's always a good idea to set a condition on your jQuery extensions so that they only run when needed instead of all the time and everywhere
In this extension, I have set the following:
jQuery Selector: '#MyID_1, #MyID_2, #MyID_3' -- yes you can pass a list of selectors or nearly any other valid jQuery selector statement
Trigger On: 'click'
Tracking Event: 'view'
3 Variables:
a. 'page_name' : $(this).text(); //get the link text
b. 'my_url' : utag.data['dom.url']+$(this).attr('href') //building the full URL including the fragment
//utag.data['dom.url'] is a variable/datapoint that Tealium automatically generates
c. my_path : utag.data['dom.pathname']+$(this).attr('href'); //building the path
//utag.data['dom.pathname'] is a variable/datapoint that Tealium automatically generates
NOTE: make sure to set the type for each these to "JS Code" otherwise your JavaScript will be quoted out as a string.
Why these three variables? As I understand GA, these are the values it would expect for a new page view -- location/URL, path, and Title so we are constructing those values in the extension to pass them to GA on the view event.
Now, we just need to map these new variables to GA.
my_path gets mapped to page in the GA mapping toolbox
page_name gets mapped to title
location isn't a default option in the mapping toolbox so we need to add a custom destination variable called location and map my_url to it.
custom variable mapping for GA
That's how you do it from within Tealium and minimal coding. If for some reason you don't want to / can't do it inside of Tealium, this provides us with a very nice template for a custom function to add to our codebase:
`$(document.body).on('click', '#altID', function(){
utag.view({
"page_name": $(this).text(),
"my_url": utag.data['dom.url'] + $(this).attr('href'),
"my_path": utag.data['dom.pathname'] + $(this).attr('href')
})
})`
See both in action over here at CodePen.

Related

Google Tag Manager - collect data attributes without using the datalayer

I'm trying to collect the value of data attributes when clicking on the element containing it but I would like to do it without using the datalayer.
I'm currently using the datalayer by pushing the data attribute into the datalayer with javascript, everything works but it's annoying to always modify the code, I'd like to do the same without using javascript.
My code looks like this:
link label
In Google Tag Manager, I have created an "automatic event variable" (not sure it is called like this in English, my GTM is in French) using the name "Generic_Dataset_product" where I select "element attribute" and as an attribute, I have tried multiple things without success like data-product, gtm.data-product, product, ...
To use this variable I have created a simple trigger that detects clicks on class "link_class" and associated an event (event_category, event_action, event_label) where I add the collected variables with the right name {{Generic_Dataset_product}}. Instead of seeing the expected value, I see "track_event".
Is there a way to collect data this way? I want to use the "automatic event variables" to collect content from src, data attributes, and other elements in the code as there are no predefined variables for this in GTM.
Thanks
Getting arbitrary attributes of clicked elements in GTM is a trivial task. And there are many ways of doing it. I prefer CJS cuz I often need to do mutations and sanitizing there. Your problem is that you're not debugging it properly.
First, make a trivial CJS variable like so:
function(){
return {{Click Element}}.getAttribute("data-shop");
}
Now open your preview debugger and actually go inspect all variables GTM sets on your click. Including your new CJS var as well as your auto-event vars. If you don't find what you're looking for from there, come back here and show us screenshots from the actual debugger and let's debug from there.
Here's how you enable {{Click Element}}:
There is no reason to avoid the datalayer. The datalayer already contains the clicked element, and the data attributes are properties of that element, so you can address them via dot notation like this:
This saves you custom javascript (which is something you might want to avoid if you ever plan to implement a proper content security policy, since custom scripts require the use of eval).

Use google tag manager install GA4 for SPA but the field page is not work

I use Google Tag Manager to install GA4 for SPA (single page application).
I search a lot of articles about setting SPA and it seems like I need to add a page field.
I tried to put the value as below but not one succeeded. I used Google Tag Manager debug mode to check the page view event was hit.
{New History Fragement}
{Page Path}{New History Fragement}
{Page Path}#{New History Fragement}
constant like /testGTM
custom javascript like below
function() {
  return window.location.pathname + window.location.search + window.location.hash;
}
Even I put the constant like testGTM, I still can not see the data contain testGTM. The page view data is collected but the URL is not the same as I expected. 
Did anyone meet the same problem? Or the field page doesn't work anymore.
Thank you.
Sample Setting GA4 in Google Tag Manager
I found out how to solve this problem.
First, click 「event」->「All event」.
Second, click「custom definition management」.
Last, click 「create custom dimension」and enter "page" in the parameter name.
After the above instruction, we can get the "page" data as normal.
How to Check
There are 3 ways to check
1.Engagement -> Event -> + custom(event scope)
2.Engagement -> Event -> click each event -> see past 30mins event's parameters
3.Engagement -> Event -> click each event -> scroll down to see parameter
P.S. I use the Japanese version so maybe the translations are different.

"Just Links" Event firing after "History Change" event

Google Tag Manager (GTM) has a built in trigger called "Just Links". In my VueJS application, using Vue Router, GTM fires a "History Change" event before firing the "Just Links" trigger.
(the "History Change" event has nothing to do with page view events)
Because of this, the Page Path GTM data-layer variable, which is supposed to be the path that the event was triggered on, is the same value as the Click URL GTM data-layer variable, which is the href value in the <a/> tag.
For instance:
User is on /support
User clicks on link to /about
Vue Router update browsers history
History Change event fires and updates all the internal values of Google Tag Manager data layer (including location and page path)
"Just Links" event fires, Page Path and Click URL values are now both /about
I'm assuming GTM/Google Analytics have some type of built in deferment strategy in place to not interfere with other things running on the main Javascript thread. So Vue Router changes routes (hence triggering the history change) before GTM/Google Analytics fire the "Just Links" trigger event.
(Strangely enough, when you use the built in Click - All Elements in GTM, the events fire in the right order.)
Has anyone else encountered this issue and come up with any type of solution? There might be a solution with just using Click - All Elements but that by default doesn't traverse the DOM tree with <a/> and strip the href for the Click URL value, which means extracting the href value on nested elements within an <a/> doesn't work. However, Just Links does do this.
Thanks!
You can look at tag firing priority. Adjust the click tag to have higher priority than the tag that's dependent on the history change trigger.
I just ran into this problem due to a site update. Instead of switching all of my "Just Links" to "All Elements" and dealing with the many headaches, I created a new Variable to reference for the page path instead of the built-in "Page Path" Variable. This Variable is basically storing what "gtm.linkClick" now treats as the previous page path because of the History Change. I'm just at beginner-level JS, so I'm sure there is a better way to write the code, but it works.
The first step is to create a new Custom HTML Tag (name it whatever you want) set to fire on All Pages and History Changes. The Tag will first attempt to store the current page path into Session Storage, or fallback to a cookie if Session Storage is not accessible. I used the {{JS - setCookie}} Variable method that was created by Simo Ahava to set cookies. There is a 2 second delay before writing the page path to storage, which is plenty of time for the "Just Links" Trigger to fire and receive the "correct" value before it is overwritten on the next pageview or history change. I gave the sessionStorage and cookie the same name "gtm.truepage".
Custom HTML Tag
<script>
function truePage() {
try {
var page = document.location.pathname;
var storage = window.sessionStorage;
if(storage) {
setTimeout(function() {
storage.setItem("gtm.truepage", page);
},2000);
} else {
setTimeout(function() {
{{JS - setCookie}}("gtm.truepage",page,1800000,"/",window.location.hostname);
},2000);
}
} catch (e) {
}
}
truePage();
</script>
Custom HTML Tag Screenshot
1st Party Cookie Variable
The next step is to create a new 1st Party Cookie Variable named "gtm.truepage". This Variable will be used as a reference for the Custom Javascript Variable. Therefore, if you change the name, you will also need to change the name in the next part.
Cookie Variable Screenshot
Custom Javascript Variable
The final step is to create a Custom Javascript Variable (whatever name you want) that you will use for your "Clicks - Just Links" Trigger. The script will first attempt to retrieve the page path that was set by the Custom HTML Tag from Session Storage and then try the 1st Party Cookie Variable.
function() {
return window.sessionStorage.getItem('gtm.truepage') || {{gtm.truepage}};
}
Custom Javascript Variable Screenshot
You can add an after hook to your router to create a custom path variable like this:
router.afterEach((to) => {
window.vuePath = to
}
Then in Google Tag Manager create a new User-Defined Variable with the JavaScript Variable type called Vue Path. Set Global Variable Path to window.vuePath.
Now you can use Vue Path instead of Page Path in your Triggers to get the correct page path.

Google Tag Manager - Returning a href from another element when a click tag is fired

I'm working on Google Tag Manager/Analytics for a site, here's an example page that a tag is being fired on:
https://www.forktrucktraders.co.uk/listings/refurbished-combilift-multi-directional-gas/
The tag is fired when the "Send Message" button on the contact form is clicked:
https://imgur.com/a/qTPb3Ci
Right now I've got the event's action returning the URL of the current page the form was sent from, but I'd like to know if it's possible to get the href from the "Visit dealer's website" link on the page, as it would give a faster idea of which dealer the listing is coming from. Probably a long shot to make this happen solely through Tag Manager (if not possibly just a hidden bit of data that just has the dealer's name in on the "Send Message" button) but I'd appreciate any input.
You most certainly can. Off the top of my head something along the lines of the following should work...
It depends on whether you prefer just having the url or breaking it down further.
Just the URL:
Create the following in a custom HTML tag within GTM
<script>
//This selects your desired href:
var dealerURL = document.querySelector(".stm-dealer-image-custom-view a").href;
//This pushes the value into the dataLayer temporarily for use later:
window.dataLayer.push({
event: 'formSubmit',
dealer: dealerURL
})
</script>
Ideally, this should be fired on page load of all your listings pages.
Next create a new User-Defined Variable of the dataLayer var type
within GTM corresponding to dealer, this will store the value to be
pulled through in your event.
Now just change your event action to {{dealer}} (or whatever you
ended up naming the datalayer variable), and this value should be
pulled through in your event.
Getting the dealer name:
Now presuming the href format is always the same across the site you could split this by a delimiter instead:
var dealerURL = document.querySelector(".stm-dealer-image-custom-view a").href;
var dealerSplit = dealerURL.split("/");
var dealer = dealerSplit[4];
The above would leave you with a variable containing the string 'hitec'.
This however is quite prone to breaking if the page path does not always follow the same format, as such it would be better to use RegEx instead.
To answer your specific question, you would need to create a variable to target that specific link element that contains the dealer's website's url. The simplest way is probably to add an id to the <a> element and create a variable in GTM to track it.
I had a quick look at your site and I think you have more problems with the form.
Your even triggers without validating the form, this would lead to extra events.
The event category, action and label could use some work in organizing it to help you analyze the data
You also have a mix of gtag.js and GTM snippet on the page, I would say this is not normal practice, usually, GTM is enough. You can contact me through my profile if you'd like to chat more about it.

SSRS and Interactive Sorting work in MVC4

I have implemented a reporting engine in mvc using html rendering. I had to create custom paging functionality based on the metadata returned via the render method. I am now looking at implementing interactive sorting in the same fashion which is looking like a more daunting task. It seems there is a setting in the HTML Device Information Settings header for html rendering called ActionScript.
ActionScript(*)-
Specifies the name of the JavaScript function to use when an action event occurs, such as a drillthrough or bookmark click. If this parameter is specified, an action event will trigger the named JavaScript function instead of a postback to the server.
My question is has anyone used this feature? Since I lose authentication after the report is rendered I will have to somehow make authenticated callbacks in the controller. It seems to me it may be easier just to add parameters for sorting in the report, however I would like to keep the interactive sorting in the report.
--Edit Solution1---
It turns out that the * next to script name above means the ActionScript parameter is being depreciated after ssrs 2012. Thus, I decided not to pursue it. If anyone else stumbles upon this then the best way I thought of to simulate interactive sorting without post backs is detailed below:
On the Report
1. Add a parameter to the report SortField1
2. Add a Sort condition to the Tablix or group you wish to sort. Tablix-Sort Expressions
3. Set the expression of the sort to Fields(Paremeters!SortField1.Value).Value
4. Set the default value of parameter SortField1 to the default sort field
5. Set Allow Nulls of the parameter to true.
6. Add a image or label for each column you would like to sort by
7. Create a action for the element created in step 7 with code similar to
="javascript:void(reportSortRequest('ColumsFieldName'))"
NOTE: Your view or view descendant will have need to have an identical function defined to accept the action
In the View
Implement the function reportSortRequest(fieldName). This should set
Model.SortField1 and invoke the post back to the controller to
re-render the report.
In the Controller (This is for Ajax post backs that sends a model that will have a field SortField1)
Call the render with report information including SortField1.
Updated with client script that works to access the report markup wrapper.
The report element generated by the ssrs markup can be accessed in your view by its tags. I have that found the following will work using the predetermined ssrs wrapper element #oReportCell":
Loaded in iframe :
var frameContent = $("#myIFrame").contents();
var ssrsContentElement = frameContent.find("#oReportCell");
Loaded in div:
var ssrsContentElement = $("#myDiv").find("#oReportCell");
Function to load html blob into either a frame or a div. Depending how the report was configured, the content is either a url of a temp file or the html markup.
function setReportContent(content, isUrl, renderInIFrame) {
if (isUrl) {
if (renderInIFrame) {
$("#reportContent").html("<iframe id='reportFrame' sandbox='allow-same-origin allow-scripts' width='100%' height='300' scrolling='yes' onload='onReportFrameLoad();'\></iframe>");
$('#reportFrame').attr('src', content);
}
else
$("#reportContent").load(content);
}
else {
if (renderInIFrame) {
$("#reportContent").html("<iframe id='reportFrame' sandbox='allow-same-origin allow-scripts' width='100%' height='300' scrolling='yes' onload='onReportFrameLoad();'\></iframe>");
$('#reportFrame').contents().find('html').html(content);
}
else
$("#reportContent").html(content);
}
if(!renderInIFrame)
showReportWaitIndicator(false);
$("#reportContent").show();
}
Notice that if you want report images with auto-resize property set to be rendered correctly you have to turn on allow-scripts so that the ssrs resize js functions can fire, be careful.

Resources