We are using two trackers on our website GaTracker and KISSmetrics on our website. We are using Segment.io as an even abstraction layer. Now we want to extend the functionality of our script that is for some events I want to call GaTracker and for some events I want to call KISSmetrics, how can I do that ?
Firstly, I'd like to mention that Segment.io uses analytics.js as the javascript client, which is open source and you can check out the source code anytime.
If you enable GA and KM on Segment.io, analytics.js will bring the GA and KM snippets onto the page, so you can still interact with the "_gaq" or "_kmq" globals as you have done in the past. You'll want to wrap your calls to the globals using the analytics.ready(..) method, like so:
analytics.ready(function () {
_gaq.push(['_addTrans',
'1234', // transaction ID - required
'Acme Clothing', // affiliation or store name
'11.99', // total - required
'1.29', // tax
'5', // shipping
'San Jose', // city
'California', // state or province
'USA' // country
]);
});
analytics.ready(..) will call the callback function when the _gaq and km variables have been loaded (think of it like the jquery $.ready document ready handler).
You can set the integrations key in the options argument for alias, group, identify, page and track
analytics.identify('019mr8mf4r', {
email: 'achilles#segment.com',
plan: 'Premium'
}, {
integrations: {
'All': false,
'Mixpanel': true,
'KISSMetrics': true,
'Google Analytics': false
}
});
https://segment.com/docs/libraries/analytics.js/#selecting-integrations
Related
I have used a button for inserting events but when i click button again it inserts again and created a duplicate copies of events. Is there any way to only insert latest events.
{
var request;
for (var j = 0; j < this.state.syncEvent.length; j++) {
console.log("J loop", this.state.syncEvent[j]);
request = function (resource) {
return gapi.client.calendar.events.insert({
'calendarId': 'primary',
'eventId': resource
});
}(this.state.syncEvent[j]);
request.execute(function (resp: any) {
console.log(resp);
});
}
}
If you are inserting an event with a predefined event id - check first if an event with this id already exists
First of all, there are some problems with your code.
Have a look at the Javasript sample in the documentation:
The correct syntax would be:
var request = gapi.client.calendar.events.insert({
'calendarId': 'primary',
'resource': event
});
whereby event is the event resource of type
var event = {
...
'start': {
'dateTime': '2015-05-28T09:00:00-07:00',
'timeZone': 'America/Los_Angeles'
},
'end': {
'dateTime': '2015-05-28T17:00:00-07:00',
'timeZone': 'America/Los_Angeles'
},
'id': SPECIFY_HERE_THE_EVENT_ID,
...
};
The event resource must contain the Required Properties end and start, in addition you specify additional properties mentioned in the documentaiton of the method like e.g. summary or id.
Now, since from your code snippet one can deduct that you pass the event id to your function - before inserting the event, you can check with the method Events: get either an event with the given id already exists.
Alternatively, you can also use the method Events: list to retrieve the already existing events in your calendar. Thereby you can use the query parameter q to filter by e.g. summary or you can query by specifying the paramters timeMax and timeMin - depending on your use case.
All you need to do is to implement a conditional statement to create a new event only if Events: get or Events: list did not return an already existing event with the specified parameters.
I have tried to get the client ID with custom javascript but it cannot return the value. Below is the code is tried. Would like to seek help from all experts. Thanks.
function () {
return function () {
try {
var trackers = ga.getAll();
trackers.forEach(function(tracker) {
var cid = tracker.get('clientId');
tracker.set('dimension1', cid);
});
} catch (e) {}
}
}
It cannot return a normal client ID
Your custom variable returns a function, not a value (since the function is never actually executed).
A better way to get the clientId for each current tracker is to use a custom task in Google Analytics (tasks are basically individual steps in the tracker lifecycle, from checking if a client id exists to assemble the payload to actually sending the data). A task is a Javascript function that is added to the GA tag via the "set fields" configuration. Tasks have access to the tracker data model and can add, remove or modify values from the payload.
The only task you can use via GTM is the customTask, which as the name suggests, adds custom capabilities to the tracker.
If you create a custom javascript variable called e.g. "getClientId" with the following code:
function() {
// Modify customDimensionIndex to match the index number you want to send the data to
var customDimensionIndex = 5;
return function(model) {
model.set('dimension' + customDimensionIndex, model.get('clientId'));
}
}
then go to your GA settings tag, and in the "set field" configuration set the field name "customTask" with the variable as value, the clientId will be extracted from the data model and added to the payload as custom dimension.
Better than my explanation is Simo Ahavas GTM tip for setting the client id via custom tasks.
I'm noticing double entry in google analytics. I have multiple ocurrences where it looks like the user came from the CPC campaign (which always has a 0s session duration) but that very same user also has an entry for "organic" and all the activities are logged under that.
My site is not ranked organically for those keywords. Unless a so many users come to my site, leave, and google for my "brand name" on google and revisits, this doesn't make sense.
I'm a little confused. Here's the report:
preview from google analytics dashboard
Based on the additional information in your comment, that the sites is a Single Page Application (SPA), you are most likely facing the problem of 'Rogue Referral'.
If this is the case, what happens, is that you overwrite the location field in the Analytics hit, losing the original UTM parameters, whereas referral is still sent with the hit, so Analytics recognizes the second hit as a new traffic source. One of the solutions is to store the original page URL and send it as the location, while sending the actual visited URL in the page field.
A very good article on this topic with further tips, by Simo Ahava, is available for your help.
Also please note, that as you have mentioned, that the first hit shows 0 second time on page, you might need to check, whether the first visited page is sent twice. E.g. sending a hit on the traditional page load event, and sending a hit for the same page as a virtual page view.
I have come up with a solution to this problem in a Gatsby website (a SPA), by writing the main logic in the gatsby-browser.js file, inside the onRouteUpdate function.
You can use this solution in other contexts, but please note that the code needs to run at the first load of the page and at every route change.
If you want the solution to work in browsers that do not support URLSearchParams I think you can easily find a polyfill.
Function to retrieve the parameters
// return the whole parameters only if at least one of the desired parameters exists
const retrieveParams = () => {
let storedParams;
if ('URLSearchParams' in window) {
// Browser supports URLSearchParams
const url = new URL(window.location.href);
const params = new URLSearchParams(url.search);
const requestedParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'gclid'];
const hasRequestedParams = requestedParams.some((param) => {
// true if it exists
return !!params.get(param);
});
if (hasRequestedParams) {
storedParams = params;
}
}
return storedParams;
}
Create the full URL
// look at existing parameters (from previous page navigations) or retrieve new ones
const storedParams = window.storedParams || retrieveParams();
let storedParamsUrl;
if (storedParams) {
// update window value
window.storedParams = storedParams;
// create the url
const urlWithoutParams = document.location.protocol + '//' + document.location.hostname + document.location.pathname;
storedParamsUrl = `${urlWithoutParams}?${storedParams}`;
}
Send the value to analytics (using gtag)
// gtag
gtag('config', 'YOUR_GA_ID', {
// ... other parameters
page_location: storedParamsUrl ?? window.location.href
});
or
gtag('event', 'page_view', {
// ... other parameters
page_location: storedParamsUrl ?? window.location.href,
send_to: 'YOUR_GA_ID'
})
So I have an Angular controller with a meteor helper method, as below.
function localeCtrl($scope, $reactive, $stateParams{
$reactive(this).attach($scope);
var self = this;
self.helpers({
locale: function(){ return Locales.findOne($stateParams.id)},
staff: function(){
// Load data from second collection based on current Locale.
// But how?
},
address: function(){
// Take self.location.address and massage it to provide
// google maps link. How?
}
tags: function(){
// Collect all unique instances of a given tag by
// iterating over the available locales.
// E. G. If 10 locales have the 'restaurant' tag, and 5
// more have the 'library' tag, I want an array of
// ['restaurant', 'library'] -- easy enough to do
// by iterating over the locales, but how do I do that
// reactively?
}
});
}
Unfortunately, I need to set additional properties based on the data fetched by locale(). I can't set them up when I initialize the controller because the value in locale() changes as data is fetched from the server. But I need access to the data in locale to, for example, create the google maps address, or fetch associated records. (They aren't imbedded in the locale document for reasons that I'm sure made sense at the time).
Edit:
Additionally, I'm using ground DB to store a local copy of the data for offline access, which makes life even more complicated.
Probably you best bet is to publish your collection using publishComposite which is implemented using the reywood:publish-composite package.
Add the package:
meteor add reywood:publish-composite
Now where you publish the Locales collection you would do something like this:
Meteor.publishComposite('locales', function() {
return {
find() {
//Put whatever you need in the query for locales
const query = {
_userId: this.userId
};
return Locales.find(query);
},
children: [{
find(locale) {
return Staff.find({ localeId: locale._id });
}
}]
};
});
Then in your controller before the helper you add this:
this.subscribe('locales');
Now you should be able to simply call the code like this:
this.helpers({
locale(){
return Locales.findOne(this.$stateParams.id);
}
});
And access it in the template like this:
locale.staff
Give that a try and let me know!
There are many QR codes that contains URL of website such as:(it just demos link)
http://www.popupstore.com/index.php?qrcode_type=magazine&location=Singapore
http://www.popupstore.com/index.php?qrcode_type=banner&location=Vietnam
I need a way can summary to know that where customer come from (nearly same as source/channel in Google Analytics):
Type: Mazazine, banner, etc.
Location: Vietnam, Singapore, etc.
Can anyone help me please :)
You could create two Custom Dimensions, each for Type and another for Country
As per your need define the appropriate Scope of the dimension, a Hit level or Session level scope would be appropriate.
You need to push custom dimensions into Google Analytics i.e. additonal JS code in your site.
ga('send', 'pageview', {
'dimension1': 'Magzine',
'dimension2': 'Singapore'
});
How this works
User scans the code and visits the store
Site has a JS code snippet that would get the query parameters from the URL and sets a custom dimension for each parameter
Setting the custom dimension would let Google Analytics know the value of the Type and Country
It is your JS code that tells Google Analytics what value to take for custom dimension. Google Analytics would not know that the value came from the URL.
To get a query parameter value via javascript you can refer to this answer, If you take the function provided there by Jan Turon (head over and give him an upvote of this helps you):
function getJsonFromUrl() {
var query = location.search.substr(1);
var result = {};
query.split("&").forEach(function(part) {
var item = part.split("=");
result[item[0]] = decodeURIComponent(item[1]);
});
return result;
}
You can use this to dynamically set the dimensions based on the url. You first call the function to return an JSON object that has the key/value pairs from the query parameters, then you insert the needed values to set the dimensions:
result = getJsonFromUrl();
ga('send', 'pageview', {
'dimension1': result.qrcode_type,
'dimension2': result.location
});