Still get firebase measurementId warning after relink to firebase analytics - javascript

I just tried to relink the project to firebase analytics. After that, the measurementId changed. I added new measurementId to HTML and deployed it. But, I still get a warning "The measurement ID in the local Firebase config (G-SWHXV050SE) does not match the measurement ID fetched from the server (G-9XKSB1V3PD)" and an error "GET https://www.googletagmanager.com/gtag/js?l=dataLayer&id=G-9XKSB1V3PD net::ERR_ABORTED 404"
Here is my code
<script src="https://www.gstatic.com/firebasejs/8.10.1/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.10.1/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.10.1/firebase-database.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.10.1/firebase-analytics.js"></script>
<script>
// NOTE - INCLUDE YOUR FIREBASE CONFIG HERE FOR ANYTHING TO WORK:
const firebaseConfig = {
apiKey: "AIzaSyDlJX8Aub35ObEgDcV-zk064gnKu69jI9U",
authDomain: "dogbox-multiplayer.firebaseapp.com",
databaseURL: "https://dogbox-multiplayer-default-rtdb.firebaseio.com",
projectId: "dogbox-multiplayer",
storageBucket: "dogbox-multiplayer.appspot.com",
messagingSenderId: "321715391463",
appId: "1:321715391463:web:14d4179d27e869d06c0b42",
measurementId: "G-SWHXV050SE"
};
const app = firebase.initializeApp(firebaseConfig);
const analytics = firebase.analytics(app);
</script>
I also tried adding
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-SWHXV050SE"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-SWHXV050SE');
</script>
The error changed to "GET https://www.googletagmanager.com/gtag/js?id=G-9XKSB1V3PD&l=dataLayer&cx=c net::ERR_ABORTED 404" and the warning is still the same.

Firebase is not made for reporting. Despite having impressive data framework, it's a poor reporting tool only viable for debugging. Let's just say Firebase is only good for native app tracking.
I'll give you a top-level walkthrough to properly install GA4 for web, but I won't go into details too much since it would've been a large article instead.
Remove libs you've installed so far. Whether it's analytics.js, gtag.js or firebase. Remove the datalayer declaration too, unless you know how to use it.
Register a GA4 property (if you don't have one) and set it up to your best ability. While doing so, make a source for web traffic and copy its measurement id.
Register a GTM container for web, not server-side (if you don't have one), copy its installation code and add it to your html source as GTM suggests. Feel free to ignore the part. GTM likes to pretend it doesn't need JS.
In GTM, make a GA4 pageview tag, set the measurement id that you copied from GA4 in that tag, bind it to a new pageview trigger.
Publish the container to production. Don't preview it without publishing. If a container hasn't ever been published, it will keep returning a 404. Because Google doesn't really care enough to make an automatic empty publish on container creation.
Let's test it properly now: install chrome extension from adswerve, enable it, go to your site and reload a page. Open the console. You'll see the extension logging tracking into the console.
Now go to your GA4 property, check real time data, make sure you see your hits. And other people's hits too, since you've published it.
This concludes it. Using GTM for web-tracking is the best practice for an average site.

Related

Conflict with two Google Tag Manager (GTM) accounts on same page

I have the following GTM already configured on my website:
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({
'event': 'Pageview',
'pagePath': 'https://www.googleanalytics.dev/pancakes',
'pageTitle': 'Pancake Event Signup',
'visitorType': 'customer'
});
</script>
<!-- Google Tag Manager -->
<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=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXX');</script>
<!-- End Google Tag Manager -->
As you can see, that block of code configures the window variable: dataLayer.
Through that code I fire events to GTM where I have Triggers and Tags. All of them working properly.
Now I got a request from one of my clients about configuring a GTM block of code (I think related to AdWords). That block of code corresponds to my client's GTM account (I have no access to it).
That block of code also configures the window variable: dataLayer as you can see below:
<!-- Global site tag (gtag.js) - Google Ads: YYYYYYYYYYY -->
<script async src="https://www.googletagmanager.com/gtag/js?id=AW-YYYYYYYYYYY"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments); }
gtag('js', new Date());
gtag('config', 'AW-YYYYYYYYYYY');
</script>
<!-- Event snippet for Submit lead form_NDPL conversion page -->
<script>
gtag('event', 'conversion', { 'send_to': 'AW-YYYYYYYYYYY/QmRnCPYt7M4DEOLk2eKs' });
</script>
I have the following 2 questions:
Can I have the variable: dataLayer configured on same page for 2 different GTM accounts (mine and his)? I'm worry about exposing data from my existing dataLayer to my client's dataLayer.
Instead of hardcoding my client's code on my page, could I maybe paste it into a new GTM Tag on my account and fire that tag which will take care of running his code above (i.e.: installing his GTM code and firing his event)? I don't like the idea of hardcoding others code on my website if not necessary.
Thanks!
You can. Technically. It will work, but every event pushed will be seen by both GTMs and, therefore, will trigger both containers' triggers. Unless you redefine datalayer for one of the containers.
If your client's GTM only has to be present on a few related pages, then yes, that would be a good idea.
It would be even better if you could just not install the client's GTM, but fire an event into their GA from your GTM as they need it. This would, however, imply certain work on your side, but hey, you may want that event in your GA too, or maybe you already have it anyways.
Let's take an event ticket selling website for example. Event organizers want to register their events on the site, but they also want to be able to measure user activity on their event's pages on the ticket selling website, as well as, maybe, linking their GA user ids to be able to join their users' journeys when the users navigate from the ticket selling website to the event organizer's website.
Doing all the tracking implementation for the event organizer is tedious, so it's easier to just deploy their container in the few pages that "belong" to them and be done with it. On the other hand, I've seen people just using GTM API and generating a GTM account on the fly when the event organizer is onboarding their event and indicating there that they want GTM presence.

Get Google Analytics Linker params with multiple trackers on the page

My question is for someone with experience using Google Analytics Linker Plugin programmatically. However my example has a bit complicated setup.
I'm currently working on the website which is using Google Tag Manager for loading GA scripts. It loads several GA scripts on the same page for different purposes.
This website also has a custom dropdown with related domains and I have to use GA Linker Plugin in order to keep them connected. I have to do it manually through the code on every domain element click event. I used the setup suggested by Google Analytics docs:
// inside onclick handler
ga(function(tracker) {
var linkerParam = tracker.get('linkerParam');
// apply to url and navigate window.location.href = url etc.
});
Obviously this doesn't work in my case because of multiple trackers on the page:
// inside onclick handler
ga(function(tracker) {
// tracker is undefined :(
});
I managed to check how many trackers are available and requested linkerParam on each:
// inside onclick handler
ga(function () {
var trackers = ga.getAll();
trackers.forEach(function (tracker) {
console.log(tracker.get('name'), tracker.get('trackingId'), tracker.get('linkerParam'));
});
});
// outputs
// gtm1 UA-XXXYYY-1 _ga=2.234343242.904959305.3434234324-394093204.3094039402
// gtm2 UA-XXXYYY-2 _ga=2.234343242.904959305.3434234324-394093204.3094039402
// gtm3 UA-XXXYYY-3 _ga=2.234343242.904959305.3434234324-394093204.3094039402
As you can see all trackers have the same linker param value, but different names and tracking ids. My question are -
Is it safe to use just first tracker from the list as long as all values are the same (e.g. ga.getAll()[0].get('linkerParam'))?
Or will it be safer to create a specific name for one of the GA trackers in GTM and get it by name in code, e.g:
// inside onclick handler
ga(function () {
var tracker = ga.getByName('websiteTracker');
console.log(tracker.get('name'), tracker.get('trackingId'), tracker.get('linkerParam'));
});
// outputs
// gtm3 UA-XXXYYY-3 _ga=2.234343242.904959305.3434234324-394093204.3094039402
Thanks!
You might be overthinking the problem. Google Analytics through GTM has a simple, built-in way to implement cross-domain tracking. For each GA property that you are loading through GTM, simply set the domains you want to link in the "Cross-Domain Tracking" fields of the Analytics Setting variable or in the over-riding settings in the GA tag.
Bounteous has a very detailed article on how to implement and debug this here.
This has worked in almost all cases in which I want to implement cross-domain tracking through GTM - even if it is for numerous domains.
In the case that you actually need to do this programmatically, I'm pretty sure you can use the same linker param for all the GA properties. You can verify and debug your implementation by doing something like:
Open up the real-time report in the GA property you want to test cross-domain tracking
Visit domain1.com with these UTM values appended: domain1.com?utm_source=test&utm_medium=test
You should be able to filter the real-time traffic by source / medium by clicking on "test" as source or medium under the traffic sources tab.
Navigate to the content tab of the real-time report, you should see the page path and page title for domain1.com
For each domain you want to test that cross-domain tracking works, click the link in your navigation
If everything works, your filtered real-time view should update to the page path and title of domain2.com
If cross-domain linking isn't working, the filtered real-time report will not update. Removing the filter, you should see "domain1.com / referral" or "(direct) / (none)" as the source / medium depending on your referral exclusions.
Hopefully this will help you configure cross-domain tracking or debug efficiently.

Accessing meteor settings from a <script> in a html <head>

I am trying to get one-signal to manage web push notifications in a meteor.js application. It is required that I set the below code in the head, based on Onesignal documentation (step 7). so I have placed it in a layout.html.
This works when the onesignal app ID is hard coded in, however I need to pull this key from settings.json. Simply replacing the value with Meteor.settings.public.oneSignalAppId does not seem to work and spacebars are not an option either. I would be happy to move the code if possible however I have had no luck with what I have tried (another question with some things ive tried).
<script>
var OneSignal = window.OneSignal || [];
OneSignal.push(["init",{
appId: "valueFromSettings",
}]);
</script>

Shopify App - Using Script Tags with Ruby on Rails Application

I'm trying to familiarize myself with the concept of using script tags. I'm making a ruby on rails app that does something as simple as alert "Hi" when a customer visits a page. I am testing this public app on a local server and I have the shopify_app gem installed. The app has been authenticated and I have access to the store's data. I've viewed the Shopify API documentation on using script tags and I've looked at the Shopify Embedded App example that Shopify has on GitHub. The documentation details the properties of a script tag and gives examples of script tags with their properties defined, but doesn't say anything about where to place the script tag in an application, or how to configure an environment so that the js file in the script tag will go through.
I've discovered that a js file being added with a script tag will only work if the js file is hosted online, so I've uploaded the js file to google drive. I have the code for the script tag in the index action of my HomeController (the default page for the app). This is the code I'm using:
def index
if response = request.env['omniauth.auth']
sess = ShopifyAPI::Session.new(params[:shop], response[:credentials][:token])
session[:shopify] = sess
ShopifyAPI::Base.activate_session(sess)
ShopifyAPI::ScriptTag.create(
:event => "onload",
:src => "https://drive.google.com/..."
)
end
I think the problem may be tied to the request.env. The response is not being read as request.env[omniauth.auth] and I believe that the response coming back as valid may be required for the script tag to go through.
The method that I tried above is from the 2nd answer given in this topic: How to develop rails app for shopify with ScriptTags.
The first answer suggested using this code:
ShopifyAPI::Base.site = token
s = ShopifyAPI::ScriptTag.create(:events => "onload",:src => "your javascript url")
However, it doesn't say where to place both lines of code in a rails application. I tried putting the second line in a js file in my rails application, but it did not work.
I don't know if I'm encountering problems because I'm running the app on a local server or if there is something missing from the configuration of my application.
I'd appreciate it if anyone could point me in the right direction.
Try putting something like this in config/initializers/shopify_app.rb
ShopifyApp.configure do |config|
config.api_key = "xxx-xxxx-xxx-xxx"
config.secret = "xxx-xxxx-xxx-xxx"
config.scope = "read_orders, read_products"
config.embedded_app = true
config.scripttags = [
{event:'onload', src: 'https://yourdomain.herokuapp.com/javascripts/yourjs.js'}
]
end
Yes, you are correct that you'll need the js file you want to include for your script tag publicly available - if you are using localhost for development look into ngrok.
Do yourself the favor of ensuring your callbacks use SSL when interacting with the Shopify API (i.e. configure your app with https://localhost/ as a callback setting in the Shopify app settings). I went through the trouble of configuring thin as the web server locally with a self-signed SSL certificate.
With a proper set up you should be able to debug why the response is failing the omniauth check.
I'm new to the Shopify API(s), but not Rails. Their documentation leaves a lot to be desired.
Good luck to you sir,

Google Drive API, can't open standard sharing dialog via JS (x-frame-options error)

I have a JavaScript app which uses the Google Drive API. I read how to open a standard sharing dialog here: https://developers.google.com/drive/web/manage-sharing
<head>
...
<script type="text/javascript" src="https://apis.google.com/js/api.js"></script>
<script type="text/javascript">
init = function() {
s = new gapi.drive.share.ShareClient('<MY_APP_ID>');
s.setItemIds(["<MY_FILE_ID>"]);
}
window.onload = function() {
gapi.load('drive-share', init);
}
</script>
</head>
<body>
<button onclick="s.showSettingsDialog()">Share</button>
</body>
Seems like I do everything right, when I click my share button, the dialog starts loading but it can't be loaded.
In the console I see:
Refused to display 'https://drive.google.com/share?...' in a frame
because it set 'X-Frame-Options' to 'SAMEORIGIN'.
I've googled this error and I've seen that there are some similar questions in SO and other sites, but they don't help. I guess Google doesn't allow itself to be in a frame in a not-google-site (cause of "SAMEORIGIN").
What can I do to open sharing dialog in my app?
The "Launching the Google Drive sharing dialog in your app" page here states:
The URL of the page that launches the dialog must have the same origin
as the Open URL registered for the app.
If you then look at the instructions to "Configure the Drive SDK" here, you can see that the "Open URL" section reads:
There are two important things to keep in mind for the Open URL:
Make sure you give a fully qualified domain name for Open URL -- localhost won't work.
The URL must belong to you. After the app registration is complete, you'll need to verify your ownership of this URL in order to create a
Chrome Web Store listing. For more information, see Site Verification.
Hence your page which is launching the dialog does not have the same origin as the Open URL registered for the app in you Google Drive SDK settings. So to fix your problem correct the Open URL so that it has the correct URL i.e. a URL with the same origin as the Open URL. Note that you can change the Google Drive SDK settings via https://console.developers.google.com/project.
As well as making sure the Open URL is set correctly. You'll also need to substitute your Drive SDK app ID for 'MY_APP_ID'. You can find the App ID by following these instructions:
Goto https://console.developers.google.com
Click your project
Click "APIs and auth" on the left
Click the "Drive SDK" settings cog icon
The "App ID" can then be found under the "Google Drive SDK" title e.g. App ID: 47XXXXXXXX3
The problem was solved thanks to this answer https://stackoverflow.com/a/20742994/1185123
dan-man says in his answer:
Client ID You can find this in the Google Cloud Console - see above.
Mine is a 12 digit number, so yours will probably be too.
Mine client id looks like
175564412906-ui22fsaghkvkkj09j2bprku55m8k3d0d.apps.googleusercontent.com
I've used this id in
s = new gapi.drive.share.ShareClient('<MY_APP_ID>');
After reading the answer, I tried to use only first 12 digits of my client id. I didn't expect it to work, I was just desperate. But the strange thing, it works perfectly!
If somebody can explain why it works and why nothing about this is said in the documentation — you are welcome to answer!

Categories