Limit with getting info about audience from Analytics API - google-analytics

I'm trying to get audienc name aduience id etc we' ve created on our google analytics account. We have around 2,4k audiences list but I can just get 999 of them. I can't find any soultions. Code is below
function main() {
var spreadsheet = SpreadsheetApp.openByUrl('https://docs.google.com/spreadshe');
var sheet = spreadsheet.getSheetByName('Sh');
function listRemarketingAudiences(accountId, propertyId) {
var request = Analytics.Management.RemarketingAudience.list(
accountId,
propertyId
);
var leno = Object.keys(request).length
console.log(leno);
sheet.getRange(1,1).setValue("audianceName");
sheet.getRange(1,2).setValue("audianceId");
sheet.getRange(1,3).setValue("audianceDefinition");
sheet.getRange(1,4).setValue("audianceDescription");
for ( var i = 2; i <3000; i++) {
var audianceName = request.items[i+154].name ;
Logger.log(audianceName);
console.log(i);
sheet.getRange(i,1).setValue("elo")
var audianceId = request.items[i].id ;
sheet.getRange(i,2).setValue(audianceId);
// var audianceId = request.items[i].
var audienceDefinition = request.items[i].audienceDefinition ;
sheet.getRange(i,3).setValue(audienceDefinition);
var audienceDescription = request.items[i].description ;
sheet.getRange(i,4).setValue(audienceDescription);
};
}
listRemarketingAudiences('xxxxx', 'UA-xxxxx-1');
}

Currently you are supplying only the required parameters: accountId and webPropertyId. These are necessary to identify the Analytics property, where you are looking for the data.
Based on the documentation, optional parameters can be passed, which are actually in connection with the pagination, which you are trying to achieve.
As the developer guide is not mentioning the absolute limit of the result, you could experiment with higher limits, with a code something like this:
request = gapi.client.analytics.management.remarketingAudience.list(
{
'accountId': accountId,
'webPropertyId': propertyId,
'max-results': 5000
}
If you can't get all the data at once, you need to implement paging yourself, where an other paramerer, start-index will be necessary. You need to call the function several times, preferably from a loop, where start index is continuously increased.
request = gapi.client.analytics.management.remarketingAudience.list(
{
'accountId': accountId,
'webPropertyId': propertyId,
'start-index': 999,
'max-results': 1000
}

I wrote sth like this:
var optional = {'startIndex': 12,
'maxresults': 212};
function listRemarketingAudiences (accountId, propertyId, optional){
var request = Analytics.Management.RemarketingAudience.list(
accountId,
propertyId,
optional.maxresults
);
and an error occure:
We're sorry, a server error occurred. Please wait a bit and try again. (line 9, file "Code")

Related

How to separate multiple columns from a range in an array?

I have a range of data in a Google Sheet and I want to store that data into an array using the app script. At the moment I can bring in the data easily enough and put it into an array with this code:
var sheetData = sheet.getSheetByName('Fruit').getRange('A1:C2').getValues()
However, this puts each row into an array. For example, [[Apple,Red,Round],[Banana,Yellow,Long]].
How can I arrange the array by columns so it would look: [[Apple,Banana],[Red,Yellow],[Round,Long]].
Thanks.
It looks like you have to transpose the array. You can create a function
function transpose(data) {
return (data[0] || []).map (function (col , colIndex) {
return data.map (function (row) {
return row[colIndex];
});
});
}
and then pass the values obtained by .getValues() to that function..
var sheetData = transpose(sheet.getSheetByName('Fruit').getRange('A1:C2').getValues())
and check the log. See if that works for you?
Use the Google Sheets API, which allows you to specify the primary dimension of the response. To do so, first you must enable the API and the advanced service
To acquire values most efficiently, use the spreadsheets.values endpoints, either get or batchGet as appropriate. You are able to supply optional arguments to both calls, and one of which controls the orientation of the response:
const wb = SpreadsheetApp.getActive();
const valService = Sheets.Spreadsheets.Values;
const asColumn2D = { majorDimension: SpreadsheetApp.Dimension.COLUMNS };
const asRow2D = { majorDimension: SpreadsheetApp.Dimension.ROWS }; // this is the default
var sheet = wb.getSheetByName("some name");
var rgPrefix = "'" + sheet.getName() + "'!";
// spreadsheetId, range string, {optional arguments}
var single = valService.get(wb.getId(), rgPrefix + "A1:C30");
var singleAsCols = valService.get(wb.getId(), rgPrefix + "A1:C30", asColumn2D);
// spreadsheetId, {other arguments}
var batchAsCols = valService.batchGet(wb.getId(), {
ranges: [
rgPrefix + "A1:C30",
rgPrefix + "J8",
...
],
majorDimension: SpreadsheetApp.Dimension.COLUMNS
});
console.log({rowResp: single, colResp: singleAsCols, batchResponse: batchAsCols});
The reply will either be a ValueRange (using get) or an object wrapping several ValueRanges (if using batchGet). You can access the data (if any was present) at the ValueRange's values property. Note that trailing blanks are omitted.
You can find more information in the Sheets API documentation, and other relevant Stack Overflow questions such as this one.

Performance server scripting

I have table with multiple customerKey values assigned to a numeric value; I wrote a script where foreach row of data I scan whole table to find all values assigned to the current customerKey and return a highest one;
I have a problem with performance - script processes around 10 records per second - any ideas how to improve this or maybe propose an alternative solution plesae?
function getLastest() {
var date = app.models.magicMain.newQuery();
var date_all = date.run();
date_all.forEach(function(e) { // for every row of date_all
var temp = date_all.filter(function(x) {
return x.SubscriberKey === e.SubscriberKey; // find matching records for the current x.SubscriberKey
});
var dates = [];
temp.forEach(function(z) { // get all matching "dates"
dates.push(z.Date);
});
var finalValue = dates.reduce(function(a, b) { // get highest dates value (integer)
return Math.max(a, b);
});
var record = app.models.TempOperatoins.newRecord(); // save results to DB
record.email = e.SubscriberKey.toString() + " " + finalValue.toString();
app.saveRecords([record]);
});
}
The only suggestion I have would be to add:
var recordstosave = [];
At the top of your function.
Then replace app.saveRecords([record]) with recordstosave.push(record).
Finally outside of your foreach function do app.saveRecords(recordstosave).
I saw major processing time improvements doing this rather than saving each record individually inside a loop.

Is it possible to call 2 API's and displaying a combined answer string at the same time?

I am having trouble doing just that because of the await and async functions.
I want to have an app that analize a face in real time and is displaing the rectangle on his face and above it should say gender, age, emotion, emotion confidance.
So I want to use the Face API and Emotion API at the same time.
Thanks.
Duplicate with Calling the face and emotion API at the same time.
Please refer to that thread for more information.
Assuming you're using the C# SDKs, you can wait for both tasks to complete. The code would like something like this:
static bool SameFace(Microsoft.ProjectOxford.Face.Contract.FaceRectangle r1,
Microsoft.ProjectOxford.Common.Rectangle r2)
{
// Fuzzy match of rectangles...
return Math.Abs((r1.Top + r1.Height / 2) - (r2.Top + r2.Height / 2)) < 3 &&
Math.Abs((r1.Left + r1.Width / 2) - (r2.Left + r2.Width / 2)) < 3;
}
void Test(string imageUrl)
{
var faceClient = new FaceServiceClient(FACE_API_KEY);
var emotionClient = new EmotionServiceClient(EMOTION_API_KEY);
var faceTask = faceClient.DetectAsync(imageUrl, false, false, new FaceAttributeType[] { FaceAttributeType.Age, FaceAttributeType.Gender });
var emotionTask = emotionClient.RecognizeAsync(imageUrl);
Task.WaitAll(faceTask, emotionTask);
var people = from face in faceTask.Result
from emotion in emotionTask.Result
where SameFace(face.FaceRectangle, emotion.FaceRectangle)
select new {
face.FaceAttributes.Gender,
face.FaceAttributes.Age,
emotion.Scores
};
// Do something with 'people'
}
The tricky part is that the two APIs don't have the same rectangle type, and give slightly different values, hence a fuzzy match.

How should I structure my data so it works with firebase?

I want to update some data in the forms of
wordBank = {
{word:"aprobi", translation:"to approve", count:2},
{word:"bati", translation:"to hit, to beat, to strike", count:1},
{word:"da", translation:"of", count:1}
}
the goal is to able to extract and display all the values of all the keys in each JSON object. How do I create this format on firebase? do I use .update? or something else?
currently I could only get firebase .update() to work with an array but it gives me data like this
wordBank = [
{word:"aprobi", translation:"to approve", count:2},
{word:"bati", translation:"to hit, to beat, to strike", count:1},
{word:"da", translation:"of", count:1}
];
where each word-object is an index in the array.
Here's how I construct my wordObjects:
function getWords() {
if (document.getElementsByClassName("vortarobobelo").length != 0){
var words;
words = document.getElementsByClassName("vortarobobelo")[0].children[0].children;
for (var i =0; i < words.length; i++) {
var localBank = {} //creating the local variable to store the word
var newWord = words[i].children[0].innerText; // getting the word from the DOM
var newTranslation = words[i].children[1].innerText; // getting the translation from the DOM
localBank.word = newWord;
localBank.translation = newTranslation;
localBank.count = 0 //assuming this is the first time the user has clicked on the word
console.log(localBank);
wordBank[localBank.word] = localBank;
fireBank.update(localBank);
}
}
}
If you want to store the items within an object, you need to pick keys to store them against.
You can't store unkeyed values inside an object in Javascript. This would result in a syntax error:
wordBank = {
{word:"aprobi", translation:"to approve", count:2},
{word:"bati", translation:"to hit, to beat, to strike", count:1},
{word:"da", translation:"of", count:1}
}
The other option is to store them in an array, in which case the keys will be automatically assigned as array indices. Just like your second example.
Maybe you want to store the word objects, using the word itself as a key?
wordBank = {
aprobi: {word:"aprobi", translation:"to approve", count:2},
bati: {word:"bati", translation:"to hit, to beat, to strike", count:1},
da: {word:"da", translation:"of", count:1}
}
This would be easy to do with Firebase. Let's say you have all of your word objects as a list.
var ref = new Firebase("your-firebase-url");
wordObjects.forEach(function(wordObject) {
ref.child(wordObject.word).set(wordObject);
});
Or you could create the object with Javascript, then add it to Firebase using .update.
var wordMap = {};
wordObjects.forEach(function(wordObject) {
wordMap[wordObject.word] = wordObject;
});
ref.update(wordMap);

google api .net client v3 getting free busy information

I am trying to query free busy data from Google calendar. Simply I am providing start date/time and end date/time. All I want to know is if this time frame is available or not. When I run below query, I get "responseOBJ" response object which doesn't seem to include what I need. The response object only contains start and end time. It doesn't contain flag such as "IsBusy" "IsAvailable"
https://developers.google.com/google-apps/calendar/v3/reference/freebusy/query
#region Free_busy_request_NOT_WORKING
FreeBusyRequest requestobj = new FreeBusyRequest();
FreeBusyRequestItem c = new FreeBusyRequestItem();
c.Id = "calendarresource#domain.com";
requestobj.Items = new List<FreeBusyRequestItem>();
requestobj.Items.Add(c);
requestobj.TimeMin = DateTime.Now.AddDays(1);
requestobj.TimeMax = DateTime.Now.AddDays(2);
FreebusyResource.QueryRequest TestRequest = calendarService.Freebusy.Query(requestobj);
// var TestRequest = calendarService.Freebusy.
// FreeBusyResponse responseOBJ = TestRequest.Execute();
var responseOBJ = TestRequest.Execute();
#endregion
Calendar API will only ever provide ordered busy blocks in the response, never available blocks. Everything outside busy is available. Do you have at least one event on the calendar
with the given ID in the time window?
Also the account you are using needs to have at least free-busy access to the resource to be able to retrieve availability.
I know this question is old, however I think it would be beneficial to see an example. You will needed to actually grab the Busy information from your response. Below is a snippet from my own code (minus the call) with how to handle the response. You will need to utilized your c.Id as the key to search through the response:
FreebusyResource.QueryRequest testRequest = service.Freebusy.Query(busyRequest);
var responseObject = testRequest.Execute();
bool checkBusy;
bool containsKey;
if (responseObject.Calendars.ContainsKey("**INSERT YOUR KEY HERE**"))
{
containsKey = true;
if (containsKey)
{
//Had to deconstruct API response by WriteLine(). Busy returns a count of 1, while being free returns a count of 0.
//These are properties of a dictionary and a List of the responseObject (dictionary returned by API POST).
if (responseObject.Calendars["**YOUR KEY HERE**"].Busy.Count == 0)
{
checkBusy = false;
//WriteLine(checkBusy);
}
else
{
checkBusy = true;
//WriteLine(checkBusy);
}
if (checkBusy == true)
{
var busyStart = responseObject.Calendars["**YOUR KEY HERE**"].Busy[0].Start;
var busyEnd = responseObject.Calendars["**YOUR KEY HERE**].Busy[0].End;
//WriteLine(busyStart);
//WriteLine(busyEnd);
//Read();
string isBusyString = "Between " + busyStart + " and " + busyEnd + " your trainer is busy";
richTextBox1.Text = isBusyString;
}
else
{
string isFreeString = "Between " + startDate + " and " + endDate + " your trainer is free";
richTextBox1.Text += isFreeString;
}
}
else
{
richTextBox1.Clear();
MessageBox.Show("CalendarAPIv3 has failed, please contact support\nregarding missing <key>", "ERROR!");
}
}
My suggestion would be to break your responses down by writing them to the console. Then, you can "deconstruct" them. That is how I was able to figure out "where" to look within the response. As noted above, you will only receive the information for busyBlocks. I used the date and time that was selected by my client's search to show the "free" times.
EDIT:
You'll need to check if your key exists before attempting the TryGetValue or searching with a keyvaluepair.

Resources