How do I push an object onto the dataLayer - google-analytics

I'd like to use object in the atalayer. I've followed the developer docs and they show a flat data model. I'd like to push a lead object and update it as a user enters info into a Lead form.
with company, size and location, key and value.
dataLayer.push({'event': 'company_on_blur'}); //on leaving a company field
dataLayer.push('lead.company', '<company>');
dataLayer.push('lead.size', '<company-size>');
dataLayer.push('lead.size', '<company-location>');
dataLayer.push('lead.key', '<value>');
Is there a way to push all this data as a structured lead object?
onclick="dataLayer.push({
// lead data object
});
also how can I modify just one property of an object once it is pushed
dataLayer.push({'event': 'company_on_blur'}); //on leaving a company field
dataLayer.push('lead.company', '<company>'); //update the value in the object

Yes, you can push several values at once with dataLayer.push. It will become something like this:
dataLayer.push({
'event': company_on_blur,
'lead.company': company,
'lead.size': company-size,
'lead.location': company-location,
'lead.key': value
});
To update a value in object on a given event - just use the event as a firing trigger (Fire tag X when custom event equals company_on_blur).
If your idea is to get a fields values from a form and send them to GTM - it's easier to create the variables for the values extractions, create the trigger company_on_blur and fire a tag for collecting the data. You can use also a form submit click as a trigger instead of leaving the field, if you are ok to collect these only for people which clicked the submit button. This way you will collect all data at once.

Related

GA4 with GTM - sending the items array as an event parameter without using datalayer?

Using GA4 with GTM. I'm questioning how to send an array for an event. For example, the add_to_cart event. In my situation I am triggering the tag on my purchase links. On those links I added data parameters for the id, name, and value such as :
Buy Now
There are multiple and the id, name, and value are the only things that change for each link.
Google requires an items array to be sent with the add_to_cart event. Can I enter the items array as shown in this picture using dot notation? I can't supply this information in the datalayer which is why I am grabbing the values that can be different from the link itself (data parameters)... the rest are static and won't change. I can't find any way to create an array variable in GTM so the dot notation is the only thing I could think of.
Is there another way to do this I am missing or not thinking of?
Unfortunately you can't.
Your solution sends every value from the items object as an individual event parameter.
GA4 requires you to send an array of objects, with one object for every sold item.
The good news is, you can use GTM to create the items array in the correct format using some JavaScript.
#Ramon Put me in the right direction. Set this up as a custom js variable. Since I trigger the tag on link click the {{Click Element}} lets me get those data-parameter values from it to create the array values that are dynamic. I suppose I could have also used the gtm variables I already created for those here too. Anyways, I use this variable as the items event parameter value which returns the array how I wish. Seems to be working fine.
function(){
var e = {{Click Element}};
var items = [{
item_id: e.dataset.id,
name : e.dataset.name,
affiliation : 'some name',
currency : 'USD',
item_brand : 'some name',
item_category : 'Software',
price : e.dataset.value,
quantity : 1
}];
return items;
}

GSuite Appmaker - how to set default value in table using button

I am trying to put together a mock up for a data collection app for a local nonprofit using GSuite's AppMaker. So far I really like the tool.
One thing I need to be able to do is streamline the data entry for the site representatives. In my app, I display a list of students in a table, where one of the columns is a boolean value which represents attendance. The desired result is for the teachers to be able to input the date field one time using the date input button at the bottom of the page. Then they can quickly point and click down the Present column to log attendance.
My question is: how would I link the date selector dropdown so that the date field pre-populates with the selected date from the input field? I don't want them to have to enter the field over an over again since its the same for each row and I don't want the user experience to feel clunky.
Screenshot of the App for reference:
Using client script, you can add the following to the onValueEdit event handler of the date widget at the bottom.
var items = widget.root.descendants.<YourTable>.datasource.items;
items.forEach(function(item){
item.<DateField> = newValue;
});
The only thing to take into account is that when using client scripting, you will only update the records loaded in the table at the moment; i.e, if your table has paging, it will only update the current page. If you are using paging, then you will need to add the following code to the onPreviousClick and the onNextClick event handlers of the pager widget:
var selectedDate = widget.root.descendants.<YourDatePicker>.value;
var items = widget.root.descendants.<YourTable>.datasource.items;
items.forEach(function(item){
item.<DateField> = selectedDate;
});

How do I fire a tag in GTM when a value appears in my data layer?

My website loads values into my data layer after the website loads. I'd like to fire tags when certain values appear in my data layer, and incorporate my data layer items into the tag (for example, an order id).
How can I achieve this?
Thanks!
I assume you are doing a "push" to the dataLayer. Push a variable with the key "event" along with your orderid:
dataLayer.push({
'orderid' : '12345',
'event' : 'myEvent'
});
Then create a trigger type custom event where "event name equals myEvent' and use this to trigger your tag:

Already save has_many relation in getCMSField_forpopup records in appearing again in every new records in SilverStripe

I have one getCMSField_forpopup form for an event. I made another popup inside that to give multiple dates to that event(using has_many relation). When I give date 2 different dates/times to event "A" and then after saving event "A", I open main getCMSField_forpopup to enter details of another event "B" then I see dates/times (complextablefield) already there which were actually meant to appear in event A's detail not in event "B". I want to see those only with A not with every new event. How can I make that possible ?
Your problem is that you enter Dates for 1 Event, but then you can see this Dates on every single Event?
to me this sounds like either your Event has no ID at this time and therefore a query on Dates "WHERE EventID = x" does not work, or your Dates get saved without the ID of the Event
You could simply check your database if your Dates have the ID of an Event set.
If the ID if the Event is 0, then the issue is that you are not saving the event ID, this either means that:
you have created the Dates before saving the Event, in this case the solution is just saving the Event before you add Dates, you could also hide the Dates field when it has not been saved, see below the $this->isNew() stuff
or silverstripe fails to save the EventID, in this case you could fix it by adding a hidden field to your getCMSFields_forPopup of the Date and save the Event ID there, but its gonna be a little tricky getting this ID into the popup
if this is not the issue, then the problem is that when you create a new Event it has no ID, and therefore can not filter by ID, you can simply do this inside your getCMSFields_forPopup of the Event:
if (!$this->isNew()) {
// add your ComplexTableField for Dates here so it only
// gets added if this record has already been saved
}
But actually I would recommend using nested DataObjectManager (a DataObjectManager inside a DataObjectManager)(see tutorial on youtube: http://youtu.be/eeXOTlXFmQQ), DataObjectManager does all that work for you, so this problem should not occur.
It only displays the DataObjectManager for Dates if you have already saved the Event once, otherwise it tells the user that he needs to save it first.
And it also sets the Event ID on the Dates for you
Or, even better, you could upgrade to SilverStripe 3, where you can use GridField.
GridField works way better then DataObjectManager and looks a lot nicer.

Processing variable number of form fields

I am working on a form which displays information about orders. Each order has a unique id, but they are not necessarily sequential on the form. Also, the number of fields can vary (one field per row on the form). The input into the form will not be mapped straight into the database, but will be added to the current value in the database, and then saved. An example of the form is in the picture below - the callout on the right shows the id for each row.
I know how to generate the form like this, but I can't work out how I can easily process each of these rows reliably. I also know how to give each of the fields a unique identifier, like name="order-23" or name="order[23]", but how can I translate that name so that I can update the related record in the database?
EDIT: One solution I can think of would be to iterate through every form field in the FormCollection, and if the name of the field matches the pattern, then I will extract the number from that field-name and process it.
However, I feel that there must be a much easier way to go about it - this method would likely involve a fair bit of string processing on each field, and there would possibly fall over if I have to add extra fields for each row later on.
Don't you have a list of IDs after postback? I believe you should not depend on what IDs are actually sent from the form, as anybody could change the IDs on the form to whatever they want, so it's a security issue. So you should after postback have a list of IDs you want to update (the same list you used to create the form with). In that case, you know exactly what id string you should use to retrieve the value from FormCollection.
In case you really can't get the list of IDs you are going to update, just use the FormCollection iteration as you suggested in your comment. The string processing is not that expensive in comparation with all other stuff being done at request processing.
If you have the names, then simply read the values by using Request.Form["order-23"] or re-create the controls in page pre-init and you'll have access to the values in your save event directly through the created controls.
I've done this loads in my CMS.
Essentially i sort of cheated.
The idea is something like this ....
render the form to the client, then look at the source code gneerated.
You should see that it generated a form tag with an action attribute.
When you click the submit button the form will be sent to that url so in the case of an order submission you would post the page back to OrderPage.aspx?OrderId=xxxx
then on the server you would build an update statement for your db that contained something like ...
"Update orders where order id =" + request.querystring["OrderId"]
So how do you update the action ...
In the calling page lets say you have a link called "New Order", when that link is clicked you need to do 2 things ...
redirect to this page.
generate an order id for this new order.
ok the first is simple, simply link it to this page.
the second ...
if this page is not a postback if(!IsPostback) { /* get a new id */ } depending on your order id's this may involve generating a new guid or doing something like getting the next number in a list by doing a select max(id) from a db.
once you have this new id you should still be in the page_load event.
this.form.Action = this.form.Action + "?OrderId=" + yourNewOrderId;
... tada ...
Send page back to the client.
view the source.

Resources