Organic Search Segment in Google Analaytics API for Apps Script - javascript

I'm trying to get all organic entrances for a single URI. I filtered for ga:pagepath==uri and tried to use the segment ga:organicSearches. However the segment doesn't seem to work! I get the following error: "Invalid value 'ga:organicSearches' for segment parameter" Any ideas on how to fix this?
Here is my funtion:
function getEntrancesForUri(uri) {
var endDate = '2016-01-26';
var startDate = '2015-12-28';
var profileId = xxxxxxxx;
var tableId = 'ga:' + profileId;
var optArgs = {
'filters': 'ga:pagePath=='+uri,
'segment': 'ga:organicSearches'
};
var result = Analytics.Data.Ga.get(
tableId,
startDate,
endDate,
'ga:entrances',
optArgs
);
if (result) {
return result;
} else {
return 0;
}
}

That is not how you construct a segment. Also ga:organicSearches is a metric, and you probably want to segment by a dimension.
You can use a dynamic segment as described here which would probably look like this:
sessions::condition::ga:medium==organic
This segments out sessions that have arrived via an organic search.
Alternatively you can create your segment in the GA interface and find the segment id via the Query Explorer, and use that in your query. Testing your queries in the Query Explorer is a good idea in any case, since you get instant feedback and sometimes even a useful error message.

Related

Can I use two parameter event for one function?

What I want to do is change the url.
Replace the Object word with an event parameter called e1.
Replace the word field with the event parameter e2.
I know this code is not working.
But I don't know how to do it.
The following is my code that I just wrote.
function getAllFieldValue(e1,e2) {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var url = 'test123.my.salesforce.com/services/data/v44.0/queryAll?q=SELECT Field FROM Object';
var url = url.replace('Object',e1);
var url = url.replace('Field',e2);
var response = UrlFetchApp.fetch(url,getUrlFetchOptions());
var json = response.getContentText();
var data = JSON.parse(json);
var fieldValues = data.records;
for(var i=0;i<fieldValues.length;i++){
var fieldValue = fieldValues[i].e;
ss.getRange(i+1,1).setValue(fieldValue);
}
}
I want to take the data from another database through this code and put it in the Google spreadsheet.
For e1, it means the object value selected in the dropbox.
For e2, it means the field of the object selected in the drop box.
Is there a way to use two event parameters for one function?
I look forward to hearing from you.
====================
Please understand that I am using a translator because I am not good at English.
Checking fieldValues[i] in Logger.log returns the following values:
[{
attributes={
type=Account,
url=/services/data/v44.0/sobjects/Account/0015i00000BS03VAAT
},
Name=University of Arizona
},
{
attributes={
type=Account,
url=/services/data/v44.0/sobjects/Account/0015i00000BS03TAAT
},
Name=United Oil & Gas Corp.
},
{
attributes={
type=Account,
url=/services/data/v44.0/sobjects/Account/0015i00000BS03ZAAT
},
Name=sForce
}]
The issues I am currently experiencing are as follows.
If I select 'Name' from the drop-down list, ec2 becomes 'Name'.
As far as I'm concerned,
var fieldName = fieldValues[i].e2 is
var fieldName = fieldValues[i].Name
It means that.
I think fieldValues[i].e2 should return the values of University of Arizona, United Oil & Gas Corp, sForce.
But in reality nothing is returned.
var fieldName = fieldValues[i].Name works properly.
I think there is a problem with fieldValues[i].e2
This is the problem I'm currently experiencing.
There was no problem with the parameters e1, e2, which I thought was a problem. The reason why the code did not work is because of the for loop var fieldValue = fieldValues[i].e; Because it didn't work properly.
var fieldName = fieldValues[i].e2
to
var fieldName = fieldValues[i][e2]
After modifying it like this, the code works properly.

2D Arrays in Google Apps Script

I am self taught with Apps Script, so generally approach one problem at a time, as it comes up. Arrays are confusing!
I am using an API to get the number of social followers for Facebook, Twitter and Instagram accounts. Here is the code so far. Note I have removed the API call specifics for privacy, I have also used fake profile ID's in the above, for example 1111 = Facebook, 2222 = Twitter, etc...
var response = UrlFetchApp.fetch(endpointUrl, params);
var jsonss = JSON.parse(response.getContentText());
var dataset = jsonss.data;
Logger.log(dataset);
[{dimensions={customer_profile_id=1111, reporting_period.by(day)=2021-10-31}, metrics={lifetime_snapshot.followers_count=407919.0}}, {dimensions={reporting_period.by(day)=2021-10-31, customer_profile_id=2222}, metrics={lifetime_snapshot.followers_count=1037310.0}}, {dimensions={reporting_period.by(day)=2021-10-31, customer_profile_id=3333}, metrics={lifetime_snapshot.followers_count=806522.0}}]
then map the array -
var followers = dataset.map(function(ex){return [ex.dimensions,ex.metrics]});
Logger.log(followers);
[[{reporting_period.by(day)=2021-10-31, customer_profile_id=1111}, {lifetime_snapshot.followers_count=407919.0}], [{reporting_period.by(day)=2021-10-31, customer_profile_id=2222}, {lifetime_snapshot.followers_count=1037310.0}], [{customer_profile_id=3333, reporting_period.by(day)=2021-10-31}, {lifetime_snapshot.followers_count=806522.0}]]
Now I get stuck, I am not sure how to get 'followers_count' when 'profile_id=1111', can someone please help? I have tried using another map function ( var followers = dataset.map(function(ex){return [ex.dimensions.map(function(ex2){return [ex2.followers_count]}]}); ) however this doesn't work...
Any suggestions to push me in the right direction is very much appreciated!
If Logger.log(followers); is [[{reporting_period.by(day)=2021-10-31, customer_profile_id=1111}, {lifetime_snapshot.followers_count=407919.0}], [{reporting_period.by(day)=2021-10-31, customer_profile_id=2222}, {lifetime_snapshot.followers_count=1037310.0}], [{customer_profile_id=3333, reporting_period.by(day)=2021-10-31}, {lifetime_snapshot.followers_count=806522.0}]] and you want to retrieve the value of lifetime_snapshot.followers_count: 407919 by using customer_profile_id: 1111, how about the following sample script?
Sample script:
In this sample script, your values of followers is used.
const profile_id = 1111; // Please set customer_profile_id you want to use.
const res = followers.reduce((ar, [a, b]) => {
if (a["customer_profile_id"] == profile_id) {
ar.push(b["lifetime_snapshot.followers_count"]);
}
return ar;
}, []);
if (res.length == 0) return;
const followers_count = res[0];
console.log(followers_count);
When this script is used for your values of followers, I thought that 407919 is retrieved.
If the same IDs are existing, you can retrieve them using console.log(res).
Reference:
reduce()

how do I loop through this database and get the child values?

I have this database, which looks like this
so the first keys are user uid taken from auth, and then the username he/she provided and what did they score for each match are taken also..
I just wanted to get each user total points - for example Ray total points is 45 and Wood total points is 44 but after looking through for the docs all I was able to do was just for one user, I have to write each user name and the specific match for each line to get the value.. now think of how it will be if they are dozens of users? hmm a lot of lines..
here is the JSON
the javascript code
var query = firebase.database().ref();
query.once("value")
.then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var key = childSnapshot.key;
var Data1 = childSnapshot.child("Ray/Match1/Points").val();
var Data2 = childSnapshot.child("Ray/Match2/Points").val();
console.log(Data1 + Data2);
});
})
which will let me display, Ray total points, but not for Wood obviously I have to repeat it and write it..
So how do i solve this?
I took a look at your problem and I think I have your solution, or at the very least a PATHWAY to your solution. Ok, first I'll explain the basic issue, then I'll attempt to provide you with some generic-ish code (I'll attempt to use some of the variables you used). And away we go!
Basically what I see is 2 steps...
STEP 1 - You need to use a "constructor function" that will create new user objects with their own name (and/or user ID) and their own set of properties.
With that line of thinking, you can have the constructor function include properties such as "user name", "match points 1", "match points 2" and then a function that console logs the summary of each name and their total points from match points 1 and 2.
STEP 2 - You need to put the constructor function inside of a loop that will go through the database looking for the specific properties you need to fill in the properties needed by the constructor function to spit out the info you're looking for.
So... and let's take a deep breath because that was a lot of words... let's try to code that. I'll use generic properties in a way that I think will make it easy for you to insert your own property/variable names.
var user = function(name, match1, match2){
this.name = name;
this.match1 = match1;
this.match2 = match2;
this.pointTotal = function(match1, match2) {
console.log(match1 + match2);};
this.summary = function(){
console.log(name + " has a total of " + pointTotal + "
points.");};
}
the "This" part of the code allows ANY user name to be used and not just specific ones.
Ok, so the code above takes care of the constructor function part of the issue. Now it doesn't matter how many users you need to create with unique names.
The next step is to create some kind of loop function that will go through the database and fill in the properties needed to create each user so that you can get the total points from EVERY user and not just one.
Again, I will use generic-ish property/variable names...
var key = childSnapshot.key;
while(i = 0; i < key.length + 1; i++) {
var user = function(name, match1, match2){
this.name = name;
this.match1 = match1;
this.match2 = match2;
this.pointTotal = function(match1, match2) {
console.log(match1 + match2);};
this.summary = function(){
console.log(name + " has a total of " + pointTotal + " points.");};
}
}
That is a whole lot of words and the code is a hybrid of generic property names/variables and of property names/variables used by you, but I'm certain that I am on the correct pathway.
I have a lot of confidence that if you used the code and EXPLANATION that I provided, that if you plug in your own variables you will get the solution that you need.
In closing I just want to say that I REALLY hope that helps and if it doesn't I'd like to help solve the problem one way or another because I need the practice. I work a job with weird hours and so if I don't answer right away I am likely at my job :(
Good luck and I hope I helped!
simply add total node to your db
|_Id
|_ $userId:
| |_ Ray
| | |_ Match1:24
| | |_ Match2:21
| |_ total:45
and then get user`s total
var query = firebase.database().ref();
query.once("value")
.then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var total = childSnapshot.child("total").val();
console.log(total);
});
})
you can add the total node using cloud functions
Check out this implementation. No need for cloud function.
firebase().database().ref().on('value', function(snapshot) {
snapshot.forEach((user)=>{
user.forEach((matches)=> {
var total = 0;
matches.forEach((match)=> {
total += match.val().Points;
});
console.log(total);
});
});
})
If the key is the user's Id, why add yet another nested object with the user's name? Do you expect one user to have multiple usernames? That sounds weird and adds on complexity, as you have probably noticed. If you need to keep the user name somewhere in Firebase, it is recommended that you dedicate a user details section somewhere directly under the user Id key. Here is a JavaScript representation of the Firebase object structure:
{
a1230scfkls1240: {
userinfo: {
username: 'Joe'
},
matches: {
asflk12405: {
points: 123
},
isdf534853: {
points: 345
}
}
}
}
Now, getting to the total points seems a bit more straightforward, does it not? 😎
To help you without modifying your current database structure, all you need is to loop through all the userId+username+matches permutation in your database. Here is an example code to achieve just that, you do not need any special Firebase feature, just good old JavaScript for-of loop:
const query = firebase.database().ref();
query.once('value')
.then(snapshot => {
const points = {}
const users = snapshot.val()
for (const userId of Object.keys(users)) {
const userprofile = users[userId]
for (const username of Object.keys(userprofile)) {
const user = userprofile[username]
for (const matchId of Object.keys(user)) {
const match = user[matchId]
// Store the points per user, per profile, or per both, depending on your needs
points[username] = points[username] === undefined
? points[username] = match.points
: points[username] += match.points
}
}
}
})

Page is not displaying JSON object properties

My code is not playing object properties into the console, however the code displays the object just fine. What am I not able to access the information in this object?
Here is my code:
// APOD
(function Apod() {
var api_key = 'NNKOjkoul8n1CH18TWA9gwngW1s1SmjESPjNoUFo';
var url = 'https://api.nasa.gov/planetary/apod' + "?api_key=" + api_key;
var apodRequest = new XMLHttpRequest();
var apodDATA = "";
apodRequest.onreadystatechange = function() {
apodRequest.onload = function() {
var responseObject = apodRequest.response;
apodDATA = responseObject;
$("document").ready(function() {
$("#apodimage").attr("src", responseObject.hdurl);
});
console.log(responseObject.url);
};
}
apodRequest.open("GET", url, true);
apodRequest.send(null);
}());
Here is the JSON "object" that displays fine on the responseObject variable (properties are giving me undefined):
{
"date": "2016-11-06",
"explanation": "A mere 20,000 light-years from the Sun lies NGC 3603, a resident of the nearby Carina spiral arm of our Milky Way Galaxy. NGC 3603 is well known to astronomers as one of the Milky Way's largest star-forming regions. The central open star cluster contains thousands of stars more massive than our Sun, stars that likely formed only one or two million years ago in a single burst of star formation. In fact, nearby NGC 3603 is thought to contain a convenient example of the massive star clusters that populate much more distant starburst galaxies. Surrounding the cluster are natal clouds of glowing interstellar gas and obscuring dust, sculpted by energetic stellar radiation and winds. Recorded by the Hubble Space Telescope, the image spans about 17 light-years. Follow APOD on: Facebook, Google Plus, Instagram, or Twitter",
"hdurl": "http://apod.nasa.gov/apod/image/1611/ngc3603_hubble_3885.jpg",
"media_type": "image",
"service_version": "v1",
"title": "Starburst Cluster in NGC 3603",
"url": "http://apod.nasa.gov/apod/image/1611/ngc3603_hubble_960.jpg"
}
What you get from the server is probably just a string, not an object.
You can parse the JSON string and convert it to object using JSON.parse.
var obj = JSON.parse(responseObject);
console.log(obj.url);
You can check the type of the variable using typeof. So if you print console.log(typeof responseObject), you'll get "string". If it was an object, you'd get "object".
Also, since you are already using jQuery, consider doing ajax requests by jQuery itself. It would be way more elegant. Read the documentation here.
USE JSON.parse for converting your response to json because your request is returning string
Note:- Do not use $("document").ready() inside ajax response
its working fine for me
(function Apod() {
var api_key = 'NNKOjkoul8n1CH18TWA9gwngW1s1SmjESPjNoUFo';
var url = 'https://api.nasa.gov/planetary/apod' + "?api_key=" + api_key;
var apodRequest = new XMLHttpRequest();
var apodDATA = "";
apodRequest.onreadystatechange = function() {
apodRequest.onload = function() {
var responseObject = apodRequest.response;
apodDATA = responseObject;
$("#apodimage").attr("src", responseObject.hdurl);
var json = JSON.parse(responseObject);
console.log(json.url);
};
}
apodRequest.open("GET", url, true);
apodRequest.send(null);
}());

Reusing range object in Excel.run for apps for office

I am new to APPS for OFFICE
I am trying a simple code in which I Validate Excel Data.
So Rather than nesting things in ctx.sync() again and again, I am writing code like this:-
// **json** object used beneath is somewhat like:
{"Field":[
{"FieldName":"Field1", "FieldDesc":"Field 1 desc", "MappedTo":"B2", "IsMandatory":"true", "LOV":"1,2,3"}]}
// **LOV** in above json data means:- the field data can only be among the values given.
//********** MY PIECE OF CODE**************
var fieldData = "";
$.each(json, function (index, field) {
range = ctx.workbook.worksheets.getActiveWorksheet().getRange(field.MappedTo + ":" + field.MappedTo);
range.load('text');
ctx.sync();
fieldData = range.text;
if(field.IsMandatory == true && (fieldData == "" || fieldData == null))
{
headerValidation = headerValidation + "Data is required for Field : " + field.FieldDesc + "\n";
}
else if(field.LOV != "" )
{
if($.inArray(fieldData, field.LOV.split(',')) == -1)
{
headerValidation = headerValidation + "Data not among LOV for Field : " + field.FieldDesc + "\n";
}
}
range = null;
});
As can be seen, I need to read range object again and again. So I am using range object everytime with different address and calling first "load()" and then "ctx.sync()".
If i debug slowly , things do work fine but on running application i get frequent error now and then:-
The property 'text' is not available. Before reading the property's
value, call the load method on the containing object and call
"context.sync()" on the associated request context.
Please guide me how I can handle this?
Also , is my approach correct?
In terms of what's wrong, the error is next to your ctx.sync() statement.
You need it to be
ctx.sync()
.then(function() {
fieldData = range.text;
...
});
And I wouldn't forget the .catch(function(error) { ... }) at the end, either.
As far as reusing the variable or not, it really doesn't matter. By doing "range = ctx.workbook...." you're actually creating a global range variable, which is considered bad practice. Better to do "var range = ctx.workbook....". And you don't need to worry about setting it to null at the end.
One thing to note is that since you're doing this in a for-each loop, note that the number of concurrent .sync()s that can be happening is limited (somewhere around 50-60, I believe). So you may need to adjust your algorithm if you're going to have a large number of fields.
Finally, you can make this code much more efficient by simulataniously ceating all of your range objects, loading them all at once, and then doing a single ".sync".
var ranges = [];
$.each(json, function (index, field) {
var range = ctx.workbook.worksheets.getActiveWorksheet().getRange(field.MappedTo + ":" + field.MappedTo);
range.load('text');
ranges.push(range);
});
ctx.sync()
.then(function() {
// iterate through the read ranges and do something
})
Hope this helps,
~ Michael Zlatkovsky, developer on Office Extensibility team, MSFT

Categories