Googletagmanager with Turbolinks - ruby-on-rails

Can someone explain how should we properly integrate Googletagmanager with Turbolinks?
On normal pages we just copy/paste this code immediatelly after after the opening tag.
<!-- Google Tag Manager -->
<noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-******"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); //f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-******');</script>
<!-- End Google Tag Manager -->
If I copy this code inside Turbolinks powered page I can see there is only one network request (when page loads for the first time)

I got page refreshes working following this guide
It suggests that you set up a virtual url macro and pageview rule in Tag Manager, and then push it to the dataLayer:
$(document).on('page:change', function(){
dataLayer.push({
'event':'pageview',
'virtualUrl': window.location.pathname
});
});

Implement google tag manager with turbolink 5.
copy the code below and paste inside the head.
<!-- Google Tag Manager -->
<% if Rails.env.production? %>
<script>
document.addEventListener('turbolinks:load', function(event) {
var url = event.data.url;
dataLayer.push({
'event':'pageView',
'virtualUrl': url
});
});
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','[YOUR-GTM-ID]');
</script>
<% end %>
<!-- End Google Tag Manager -->

You can bind events with Turbolinks to page:load (as opposed to $(document).ready)
$( window ).on( 'page:load', function () {
// Do something
} );
Google Tag Manager's documentation specifies:
Google Tag Manager supports dynamic pages through events.
They provide some documentation about events here: https://developers.google.com/tag-manager/devguide#events - but the specific implementation will depend on what you're doing with GTM.

The two existing answers are incomplete. Here is the full solution, along with information on how to configure GTM for your change:
Add this to your site:
<script type="text/javascript">
$(document).on('page:change', function(){
var url = window.location.href;
dataLayer.push({
'event':'pageView',
'virtualUrl': url
});
});
</script>
Once you've done that, register the trigger in Google Tag Manager and associate that trigger with the desired tags.
The complete instructions are available here: http://labs.wrprojects.com/how-to-use-google-tag-manager-with-rails-and-turbolinks/

Related

How to add option in <redoc>?

I want to add some additional option to my ReDoc. For current implementation I am using json file that is generated from Swagger, and this is added in html page. Example how this is done:
<body>
<redoc spec-url='http://petstore.swagger.io/v2/swagger.json'></redoc>
<script src="https://cdn.jsdelivr.net/npm/redoc#next/bundles/redoc.standalone.js"> </script>
</body>
I use this as referent documentation: https://github.com/Rebilly/ReDoc
How can I add option object in tag and not use ReDoc object? And how can I use vendor extension e.g. x-logo?
In documentation this is set via json file, but my json file is auto generate from Swagger.
You just place the options after the spec-url in the redoc tag like this:
<body>
<redoc spec-url='http://petstore.swagger.io/v2/swagger.json' YOUR_OPTIONS_HERE></redoc>
<script src="https://cdn.jsdelivr.net/npm/redoc#next/bundles/redoc.standalone.js"> </script>
</body>
in this example on ReDoc repository you can verify it (line 22 at this moment):
https://github.com/Rebilly/ReDoc/blob/master/config/docker/index.tpl.html#L22
Important:
Remember to "kebab-casing the ReDoc options", as an example if your options are:
hideDownloadButton noAutoAuth disableSearch
YOUR_OPTIONS_HERE
should be (after kebab-casing them):
hide-download-button no-auto-auth disable-search
Your body with those options becomes like this:
<body>
<redoc spec-url='http://petstore.swagger.io/v2/swagger.json' hide-download-button no-auto-auth disable-search></redoc>
<script src="https://cdn.jsdelivr.net/npm/redoc#next/bundles/redoc.standalone.js"> </script>
</body>
Hope it will be usefull to you.
ReDoc has advanced initialization via Redoc.init so you can download the spec manually and add some postprocessing (e.g. add an x-logo).
You can pass ReDoc options as the second argument to Redoc.init:
<body>
<div id="redoc"></div>
<script src="https://cdn.jsdelivr.net/npm/redoc#next/bundles/redoc.standalone.js"> </script>
<script>
fetch('http://petstore.swagger.io/v2/swagger.json')
.then(res => res.json())
.then(spec => {
spec.info['x-logo'] = { url: "link/to/image.png" };
Redoc.init(spec, {
// options go here (e.g. pathInMiddlePanel)
}, document.getElementById('redoc'));
});
</body>
NOTE: This requires Fetch API to be available in browsers so it won't work in IE11.
You can place your options next to spec-url.
Be sure that the version of Redoc you are using, have options you want to use, you can check it by going to the specific version. github.com/Redocly/redoc/tree/vx.x.x.
As a side note features lazy-rendering in available till v1.22.3.
https://github.com/Redocly/redoc#redoc-options-object
You can use all of the following options with standalone version on tag by kebab-casing them, e.g. scrollYOffset becomes scroll-y-offset and expandResponses becomes expand-responses.

Google Tag Assistant asks feed ID

I was asked to upgrade an existing site from using the old remarketing tracking code that looked like this:
<script type="text/javascript">
var google_conversion_id = 12345;
var google_custom_params = window.google_tag_params; // this is empty
var google_remarketing_only = true;
</script>
<script type="text/javascript" src="https://www.googleadservices.com/pagead/conversion.js">
</script>
<noscript>
<div style="display:inline;">
<img height="1" width="1" style="border-style:none;" alt="" src="//googleads.g.doubleclick.net/pagead/viewthroughconversion/12345/?value=0&guid=ON&script=0"/>
</div>
</noscript>
to another method that looks like this:
<script async src="https://www.googletagmanager.com/gtag/js?id=AW-12345"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments)};
gtag('js', new Date());
gtag('config', 'AW-12345');
</script>
because it is asynchronous and should not block page loading. But the Google Tag Assistant extension that validates that tracking is set up correctly asks me to enter a "feed ID" when using the newer (gtag.js based) method. Previously it was showing Remarketing Tag as green.
Why is it needed now and not with the old code? I asked someone who has access to the AdWords account and they don't have the feed ID (or can't find it...).
I verified that the request to googleads.g.doubleclick.net/pagead/viewthroughconversion/ is sent though devtools as described in Verifiction using browser based developer tools:
https://developers.google.com/adwords-remarketing-tag/verification
Is my configuration correct?
That feed ID is related to dynamic remarketing campaigns. If you aren't running a dynamic campaign, then the feed ID shouldn't matter.
That field to enter a feed ID is there to help you with validating that your feed is working correctly.
Here is a quick video that might help clear up your questions. https://www.youtube.com/watch?v=QuOUNIFo0aQ

Google Tag Manager Preview does not display when navigating to pages with TurboLinks

I don't think GTM is recording data correctly for my Rails app. When i use the preview feature, the GTM preview data in developer tools only shows on initial page loads, subsequent page loads (using turbolinks) do not show the preview data. How should I set up GTM with TurboLinks?
I have set up my GTM in the header like this:
<script>
var dataLayer = [];
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-N7MDCP');</script>
<!-- End Google Tag Manager -->
And then at the top of the body:
<script>
<% if user_signed_in? %>
dataLayer.push({'userID': '<%= current_user.id %>'},{'userCategory': 'User'});
<% end %>
</script>
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-N7MDCP"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
<!-- Google Tag Manager trigger for Turbolinks -->
<script type="text/javascript">
var url = window.location.href;
dataLayer.push({
'event':'pageView',
'virtualUrl': url
});
</script>
<!-- End Google Tag Manager trigger for Turbolinks -->
This has to do with how the preview mode injects the debugger iframe.
It is injected on the initial page load, but since turbolinks replaced the entire body it also removes the preview panel from -ALL- subsequent page reloads.
It is sadly pretty much how it is and not much one can do about it.
Your GTM implementation is probably still working, but preview mode in Google Tag Manager is not compatible with turbolinks page reloads.
And yes, this makes debugging GTM in turbolinks enhanced sites a major pain.
dataLayer.push(
{'userID': '<%= current_user.id %>'},
{'userCategory': 'User'}
);
instead please try
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
'userID': '<%= current_user.id %>',
'userCategory': 'User'
});
This is untested.
I have noticed your use of braces '{'

Overriding data-ajax="false" from parent container in jquerymobile

I am using the method noted here in the docs to set data-ajax="false" on a parent container for my site but I do have a few cases where I want the page to load via Ajax.
Is there a way to set the default on the parent container but allow individual links to override that setting? Adding data-ajax="true" to the individual links doesn't seem to work.
To set default for full page load:
$(document).on("mobileinit", function(){
$.mobile.ajaxEnabled = false;
});
To set individual, use data-ajax=true.
Somehow other suggestions didn't work for me. But this one did work. Tested.
This script disables all ajax links in the page jquery mobile - and those that should be ajax ones can be used as the a-link below with data-ajax=true.
<head>
<!-- ..... -->
<script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
<script>
$(document).on("mobileinit", function () {
// Reference: http://jquerymobile.com/demos/1.1.0/docs/api/globalconfig.html
$.extend($.mobile, {
linkBindingEnabled: false,
ajaxEnabled: false
});
});
</script>
<script src="http://code.jquery.com/mobile/1.3.0/jquery.mobile-1.3.0.min.js"></script>
<!-- ..... -->
</head>
<body>
<a href="holysmokewheredidtheajaxgo.html" data-ajax=true>Well, I'm still ajax. That's true!</a>
</body>

How to initialize pages in jquery mobile? pageinit not firing

What's the right way to initialize objects on a jquery mobile page? The events docs say to use "pageInit()" with no examples of that function, but give examples of binding to the "pageinit" method (note case difference). However, I don't see the event firing at all in this simple test page:
<html>
<body>
<script type="text/javascript" charset="utf-8" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script type="text/javascript" charset="utf-8" src="http://code.jquery.com/mobile/1.0b3/jquery.mobile-1.0b3.min.js"></script>
<div data-role="page" id="myPage">
test
</div>
<script>
$("#myPage").live('pageinit',function() {
alert("This never happens");
});
</script>
</body>
</html>
What am I missing? I should add that if you change pageinit to another event like pagecreate this code works.
---- UPDATE ----
This bug is marked as "closed" in the JQM issue tracker. Apparently opinions differ about whether this is working properly or not.
It started working when I embedded script within page div:
<body>
<div id="indexPage" data-role="page">
<script type="text/javascript">
$("#indexPage").live('pageinit', function() {
// do something here...
});
</script>
</div>
</body>
Used jQuery Mobile 1.0RC1
.live() is deprecated, suggestion is to use .on() in jQuery 1.7+ :
<script type="text/javascript">
$(document).on('pageinit', '#indexPage', function(){
// code
});
</script>
Check the online doc for more information about .on(): http://api.jquery.com/on/
Turns out this is a bug in 1.0b3 that is fixed in the current head. So if you want a fix now, you gotta grab the latest from git. Or wait for the next release.
jQuery(document).live('pageinit',function(event){
centerHeaderDiv();
updateOrientation();
settingsMenu.init();
menu();
hideMenuPopupOnBodyClick();
})
This is working now. Now all page transitions and all JQM AJAX functionality would work along with your defined javascript functions! Enjoy!
pageinit will not fire in case it is on secondary pages ( NOT MAIN page ) if it is written in common <script> tag...
I have such a problem - on secondary pages that are not loaded with 'rel="external"', the code in the common <script> tag is never executed...
really this code is always executed...
<body>
<div id="indexPage" data-role="page">
<script type="text/javascript">
$("#indexPage").live('pageinit', function() {
// do something here...
});
</script>
</div>
</body>
althrough if you made "tabbed interface", using of "pageshow" is better
I had to put the script in the HTML page section which to me is a bug. It is loaded normally in a browser (not via AJAX) and all on a single page including javascript. We're not supposed to have to use document ready.
The easiest way I found to deal with this was to use JQM + Steal. It works like a charm as long as you put:
<script type='text/javascript' src='../steal/steal.js?mypage'></script>
Inside of the data-role='page' div.
Then use AJAX to connect anything that can use the same mypage.js and use an external link (by using the rel="external" tag) to anything that requires a different steal page.
#Wojciech BaƄcer
From the jQuery docs:
As of jQuery 1.7, the .live() method is deprecated. Use .on() to attach event handlers. Users of older versions of jQuery should use .delegate() in preference to .live().
Try this:
$('div.page').live('pageinit', function(e) {
console.log("Event Fired");
});
$(document).on("pageinit", "#myPage", function(event) {
alert("This page was just enhanced by jQuery Mobile!");
});
The events don't fire on the initial page, only on pages you load via Ajax. In the above case you can just:
<script>
$(document).ready(function() {
alert("This happens");
});
</script>

Resources