I have the below javascript code where I am pulling the destination URL and Alt attribute from the HTML element and trying to push the values in the data-layer.
I have tested the code using the console and it's pulling the desired value. my main concern is how do we push the values in data-layer. Do I need to make modifications to the code to be able to run in customHTML via GTM?
var divHead= document.getElementsByClassName('card__media-overlapping__media');
var eventhandlerdoc = function(event){
var imgURL=event.currentTarget.firstElementChild;
var imgALT=event.currentTarget.firstElementChild.firstElementChild.getAttribute('alt');
dataLayer = [];
dataLayer.push({
'expImgurl': imgURL,
'expImgalt': imgALT
}
for(var index=0; index < divHead.length; index++){
divHead[index].addEventListener('click',eventhandlerdoc,true);}
Your code as-is will break GTM if it is executed after the GTM snippet (since GTM amends the dataLayer's push method with custom code and adds several events). So you would need to make sure this is executed before the snippet, or check if the dataLayer is initalized and reuse it:
window.dataLayer = window.dataLayer || [];
Also the variables will only be available after the next event is pushed to the dataLayer, so you either need to push a custom event or wait until the next (GTM) event before you use them.
And since GTM has it's own click handler I would suggest you use that and move the javascript code to retrieve the attributes to a custom javascript variables.
Related
I create and save my lunr index this way:
require("lunr-languages/lunr.stemmer.support")(lunr);
require("lunr-languages/lunr.multi")(lunr);
require("lunr-languages/lunr.it")(lunr);
const englishItalianSupport = lunr.multiLanguage("en", "it");
let fullTextIndex = lunr(function() {
this.use(englishItalianSupport);
this.pipeline.add(improvedTrimmer); // I think this does not matter
this.ref("id");
this.field("body");
this.metadataWhitelist = ["position"];
this.add({...});
...
}
Then I save it to be reused in the following sessions.
In the lunr-languages/README.md there is this line:
If you serialize the index and load it in another script, you'll have
to initialize the multi-language support in that script, too, like
this:
lunr.multiLanguage('en', 'it');
var idx = lunr.Index.load(serializedIndex);
Is this needed? This line generates the warning: Overwriting existing registered function: lunr-multi-trimmer-en-it. Remember, this warning was generated by the this.use() call during the index generation before moving it outside the lunr() call.
Also, should I reference my improvedTrimmer when loading the index? If yes, how?
Thanks for clarifying!
In my website I'm Showing my database after user has given the database name, Is there any way I can constantly update the web shown databasebase without refreshing the page . I've tried using setInterval but it's not working for some reason .
function c(){
setInterval(beta, 1000);
}
function beta(){
var d = document.getElementById("opopo").value;
var firebaseRefff= firebase.database().ref('LOCATION/'+d);
firebaseRefff.on('child_added', snap=> {
var slot=snap.getKey();
var alloted=snap.child("ALLOTED").val();
var date=snap.child("DATE").val();
var limit=snap.child("LIMIT").val();
var time=snap.child("TIME").val();
$("table tbody").append(""+slot+""+alloted+""+date+""+limit+""+time+"Null");
});
}
You do not need, and should not use, setInterval to trigger the queries. What you have in your beta() function looks pretty good.
firebaseRefff.on('child_added', snap => {}) means "whenever a child is added under this location, trigger the callback function (empty in my example) with the parameter 'snap'". It will also be called once, initially, for each child that is already at that database reference location.
You need to make sure you've called beta() once to setup this trigger.
If you're still having problems, you might want to insert logging to make sure beta() is being called, what the full reference path is, if the callback is ever triggered, and if your jquery string is correct.
We initially push an object containing variables to the dataLayer:
dataLayer.push({
'environment': {
'userName': 'abc',
'id': 123,
'clicks': 0
}
});
We now want to increase the value of environment.clicks with every click a user makes.
How to do that? When we push it via
dataLayer.push({
'environment': {
'clicks': 123
}
});
The dataLayer Array may get 10.000s of entries. How to properly update the variable?
The way to update a datalayer variable is to push a variable, either when a "native" GTM event occurs or alongside a custom event. So basically you are it right.
As for your worries that the DL might get to many entries - the dataLayer gets a new entry on every click in any case (GTM adds that itself), so the additional entries for your variable will probably do not matter that much.
If you still want to avoid this you can update a global Javascript variable and use that in GTM. Google Tag Manager has access to all variables on your page (you will still get all the click events in your dataLayer).
The dataLayer also has a set method that allows you to write to the Datalayer directly, which is apparently what you are looking for. You need to acquire your GTM instance and then you can set values:
var gtm = window.google_tag_manager[{{Container ID}}];
gtm.dataLayer.set('balloonsPopped', undefined);
Details are e.g. here in a Bounteous article. You could use this in a custom HTML tag to update the click count before the click event fires your tag.
Also the dataLayer is reset on page load. It would take a hell of a single page app to collect 10 000s of clicks per pageview.
This is tagged Google Analytics. If you plan to track the clicks in GA remember that a GA session expires after 500 clicks, so the results might not be what you expect (also the free version only has only 10M hit per month, click tracking will quickly exhaust this). And of you want to track the number of click in GA then you would need an event or something to track the click, so the number of events is basically the metric you are looking for, or you could create a custom metric and set it to "1" in your GA call (meaning that it will be incremented by one on every call).
Quoting from the documentation:
It's important to note that pushing a variable of the same name as an existing variable to the data layer will cause the existing value to be overwritten by the new value
Simply pushing an entry with the same variable name and the updated value should work.
Couldn't you use a holder? Something like:
var click_value_holder = dataLayer.environment.clicks;
dataLayer.push({
'environment': {
'clicks': (click_value_holder + 1)
}
});
I use this code in GTM , that retrieves a number from another domain and stores it on a dataLayer value, with a dL.push. I want the variable to be available on a specific event.
(function ()
{
var callbackMethodName = "adnscallback";
window[callbackMethodName] = function(data) {
(function() {
dataLayer.push({
'event': 'ga_new',
"id2": data.uid
});
})();
}
var sc = document.createElement("script");
sc.id = "script_" + callbackMethodName;
sc.src = "https://example.site.com/getnumber?callback=" + callbackMethodName;
document.body.appendChild(sc);
})();
But I already create an event called ga_new (hardcoded, that creates all sort of values on the page) and when this codes run, it creates another event called ga_new, instead of pushing the values on the existing event. This creates issues with the tags as they are double firing.
What iam doing wrong and the push, instead of appending the data, it creates the event again?
You can not "update" a custom event. The "event" keyword is a signal to GTM that it needs to update its internal data structure with new values.
The datalayer variable in the page is an array of objects, the internal datastructure is a single object into which new values are merged, and existing values for the same keys are overwritten. GTM overwrites the native implementation of the JS "push" method with its own code that watches for the "event" keyword. So every time it encounters the "event" key changes are triggered.
You either need a different name for the event, or you change the trigger so that it only fires when both the "ga_new" event are set and the data.uid field is set.
i have a problem that i need first to get the image links from the Firebase data base then i call a JQuery code that will organize the images in a beautiful way >> But it seems that the Jquery runs before i get the images,
Help Please ..!
JS Function
new Firebase("https://zoominp.firebaseio.com/photos/"+imageID)
.once('value', function(snap)
{
link = snap.child('imageLink').val();
link = 'images/'+link;
var id = "img";
div.innerHTML += "";
});
JQuery
jQuery("#gallery").unitegallery(
{
tiles_type:"nested",
tiles_nested_optimal_tile_width:200
});
Firebase loads (and synchronizes) the data asynchronously. So the jQuery code you have, will indeed execute before the data has come back from the server.
To fix this, move the jQuery code into the Firebase callback:
var ref = new Firebase("https://zoominp.firebaseio.com/photos/"+imageID);
ref.on('value', function(snap) {
link=snap.child('imageLink').val();
link='images/'+link;
var id="img";
div.innerHTML = div.innerHTML +"";
jQuery("#gallery").unitegallery({
tiles_type:"nested",
tiles_nested_optimal_tile_width:200
});
});
I also changed once() to on(). With that tiny change, your HTML will be updated whenever the data in the database changes. Try changing the data and you'll experience the "magic" of Firebase.
Since asynchronous loading is hard to wrap your head around when you first encounter it, I highly recommend that you read the more in-depth answers to these questions:
How do I return the response from an asynchronous call?
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
Handling Asynchronous Calls (Firebase) in functions
Returning value from a jQuery function
i have never worked with a Firebase, but you will need to have your actual resources ready before running the jQuery - you cannot do this in a synchronous way, as when you call your jquery unitedGallery it is called before the .once('value') event triggers.
do you call that new Firebase(.... thing more times in a loop or something? you could do something like keeping information about whether have all the images loaded in an array. something like this: let's assume, your images are stored in an array allOfYourImages. then,
define a global variable like this
var images_loaded=[];
for(var i=0; i<allOfYourImages.length; i++){ images_loaded[i]=false; }
then i assume you somehow iterate over your pictures since you are using imageID. add an incrementing variable var image_number=0; before the iterator and do image_number++ after each image iteration. like
var image_number=0;
...iteratorofyourchoiseihavenoideawhatareyouusing...{
new Firebase("https://zoominp.firebaseio.com/photos/"+imageID).once('value', function(snap){
...DOM stuff previously did ...
images_loaded[image_number]=true;
checkAllImagesLoaded();
});
image_number++;
}
notice the checkAllImagesLoaded() function. this will look whether have all your images already loaded and fire the jQuery gallery thing, like this
checkAllImagesLoaded(){
var all_loaded=true;
for(var i=0; i<allOfYourImages.length; i++){
all_loaded &= images_loaded[i]; //in case any of the items is false, it will set the all_loaded to false
}
if(all_loaded){
..your jQuery.("#gallery").unitegallery stuff..
}
}