I have written a chrome extension which I just published to chrome store. I'd like to know all the numbers associated with it. This includes number of installs/number of active users/user activity etc.
Where do I get these numbers from? according to this question there is no way to see the total number of installs: How can I see the number of total installs for my chrome extension?
More importantly is there a way for me to setup Weekly/Monthly emails to get these numbers directly to my inbox?
There's not an official way to do this. Google doesn't provide you detailed stats for your extensions, so if you want to know the details, you should use Analytics.
Follow the tutorial here to set up your Analytics account.
To know the number of people that installs your extension you'll need to set up an Analytics account and link it to your extension, then you can use the chrome.runtime.onInstalled.addListener method to listen to the installation and send a _trackEvent to your Analytics account.
So in your background.js you'll do something like this:
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-XXXXXXXX-X']);
// where UA-XXXXXXXX-X is your Analytics Account user number
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = 'https://ssl.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
// now add a listener to the onInstalled event:
chrome.runtime.onInstalled.addListener(function() {
_gaq.push(["_trackEvent", "Installation"]);
});
You can set any combination of "category", "action", "label" after the first "_trackEvent" string calling _gaq.push(["_trackEvent", ...]). Now, every time a user installs the extension, you'll see the number of "Installation" events increase in your Analytics account.
Related
I wondered if anyone could point me in the right direction here?
I want to monitor the Google Workspace estate, and when a new user has been created send them an email. I’ve looked through the APIs but nothing is jumping out at me. But I know there are 3rd party tools out there that do this, so there’s got to be something I have missed?
I just created this script in Google Apps Script which gets and prints the list of all the users that were created today.
You can use this as a guide and keep testing with it. To accomplish this I used the Reports API to get the admin logs and get the list of all the users that were created today.
function myFunction() {
var userKey = 'all';
var applicationName = 'admin';
var optionalArgs = {
eventName:'CREATE_USER',
startTime: "2022-03-23T12:00:00.000Z",
fields : "items.events.parameters.value"
};
var rep = AdminReports.Activities.list(userKey,applicationName,optionalArgs);
const A = (JSON.parse(rep));
var totalUsers = Object.keys(A.items).length;
for(var i=0; i<totalUsers; i++)
{
var userEmail = A.items[i].events[0].parameters[0].value;
Logger.log(userEmail);
}
}
You would just need to change the startTime value according to the date you need to use and implement the part of sending the email now that you have all the email addresses.
References
API method: activities.list
Apps Script reference: Reports API
First let me state that all my coding is self taught so my knowledge is functional but not deep. I am creating a Google sheet for my HR team in my company to track Paid Time Off. I had built triggers to send emails when time was submitted. It worked before the migration to V8 but doesn't now, and I don't know enough about syntax to be able to find the issue.
function sendNotification(e){
if(e.range.getColumn()=13 && e.value='Yes')
{
//Employee Name and Email Address
var EmployeeName = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("PTO Earnings").getRange("R3");
var Employee = EmployeeName.getValue();
var EmployeeEmailRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("PTO Earnings").getRange("S3");
var EmployeeEmailAddress = EmployeeEmailRange.getValues();
//Approver Name and Email Address
var ApproverName = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("PTO Earnings").getRange("R4");
var Approver = ApproverName.getValue();
var ApproverEmailRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("PTO Earnings").getRange("S4");
var ApproverEmailAddress = ApproverEmailRange.getValues();
//HR Email Address
var HREmailRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("PTO Earnings").getRange("S5");
var HREmailAddress = HREmailRange.getValues();
//Link to Employee's PTO Spreadsheet
var SheetLink = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("PTO Earnings").getRange("R1");
var Link = SheetLink.getValue();
//Email Content
var subject = 'PTO Submitted for '+Employee+' for '+e.range.getSheet().getName()+'.';
var body = 'Dear '+Approver+','+"\n\n"+'A PTO Request has been submitted by: '+Employee+', at:'+"\n\n"+Link +"\n\n"+'Thank you.'+"\n\n"+'Imagine This HR';
var recipient = [EmployeeEmailAddress, ApproverEmailAddress,HREmailAddress];
MailApp.sendEmail(recipient, subject, body);
}
}
Please help!
Seems that un-migrating is optional, but Google is auto-migrating scripts to V8.
Part of the problem is that Google is automatically migrating scripts that pass their compatibility tests. And apparently some use of MailApp.sendEmail will pass the test but will in fact fail when the script is run.
https://developers.google.com/apps-script/guides/v8-runtime#automatic_migration_of_scripts_to_v8
This required me to revert/opt out in about 30 sheets that use MailApp just to ensure they don't fail - users really need scripts to work.
There is no mention of MailApp.sendEmail compatibility issues in any of the migration help docs.
The migration to V8 is optional. If you aren't ready or you don't have time to make your code compatible with it, just disable it. To do this, click Run > Disable new Apps Script runtime powered by Chrome V8.
It seems like a lot of triggers don't work with V8 Runtime migration.
I have a trigger on onOpen () and it doesn't work when the sheet is opened by a collaborator. However, it works well when it is opened by the owner. I haven't found a solution yet ...
I'd like to completely undo any of Gmails built in category labels. This was my attempt.
function removeBuiltInLabels() {
var updatesLabel = GmailApp.getUserLabelByName("updates");
var socialLabel = GmailApp.getUserLabelByName("social");
var forumsLabel = GmailApp.getUserLabelByName("forums");
var promotionsLabel = GmailApp.getUserLabelByName("promotions");
var inboxThreads = GmailApp.search('in:inbox');
for (var i = 0; i < inboxThreads.length; i++) {
updatesLabel.removeFromThreads(inboxThreads[i]);
socialLabel.removeFromThreads(inboxThreads[i]);
forumsLabel.removeFromThreads(inboxThreads[i]);
promotionsLabel.removeFromThreads(inboxThreads[i]);
}
}
However, this throws....
TypeError: Cannot call method "removeFromThreads" of null.
It seems you can't access the built in labels in this way even though you can successfully search for label:updates in the Gmail search box and get the correct results.
The question...
How do you access the built in Gmail Category labels in Google Apps Script and remove them from an email/thread/threads?
Thanks.
'INBOX' and other system labels like 'CATEGORY_SOCIAL' can be removed using Advanced Gmail Service. In the Script Editor, go to Resources -> Advanced Google services and enable the Gmail service.
More details about naming conventions for system labels in Gmail can be found here Gmail API - Managing Labels
Retrieve the threads labeled with 'CATEGORY_SOCIAL' by calling the list() method of the threads collection:
var threads = Gmail.Users.Threads.list("me", {labels: ["CATEGORY_SOCIAL"]});
var threads = threads.threads;
var nextPageToken = threads.nextPageToken;
Note that you are going to need to store the 'nextPageToken' to iterate over the entire collection of threads. See this answer.
When you get all thread ids, you can call the 'modify()' method of the Threads collection on them:
threads.forEach(function(thread){
var resource = {
"addLabelIds": [],
"removeLabelIds":["CATEGORY_SOCIAL"]
};
Gmail.Users.Threads.modify(resource, "me", threadId);
});
If you have lots of threads in your inbox, you may still need to call the 'modify()' method several times and save state between calls.
Anton's answer is great. I marked it as accepted because it lead directly to the version I'm using.
This function lets you define any valid gmail search to isolate messages and enables batch removal labels.
function removeLabelsFromMessages(query, labelsToRemove) {
var foundThreads = Gmail.Users.Threads.list('me', {'q': query}).threads
if (foundThreads) {
foundThreads.forEach(function (thread) {
Gmail.Users.Threads.modify({removeLabelIds: labelsToRemove}, 'me', thread.id);
});
}
}
I call it via the one minute script trigger like this.
function ProcessInbox() {
removeLabelsFromMessages(
'label:updates OR label:social OR label:forums OR label:promotions',
['CATEGORY_UPDATES', 'CATEGORY_SOCIAL', 'CATEGORY_FORUMS', 'CATEGORY_PROMOTIONS']
)
<...other_stuff_to_process...>
}
My question is about an error in Google's spreadsheet using gmail service in a function.
Since a while, an error occur when I run a function (On Google Spreadsheet) for retrieve mails on a label founded in the MailBox (Gmail).
The error message is : "Too much calls for this service today : gmail".
I want to specify that function worked fine before and it hasn't been modified.
The function is launched one time per month (Except in exceptional case)
I did some research on the error message, and the answers found confirmed what I thought,
daily quotas for Google's gmail services are exceed and can not be used until 24 hours.
However, it's the only one that has not worked, while others are working properly with these services without any errors.
Following this, I created a copy of the spreadsheet with the function to test if it isn't the sheet that does not work, but it has not changed.
And I launched it with another Google account, and it worked.
Does anyone know why this message appears please ?
Should we do a special manipulation to make it work again ?
Here is the row that sends an error :
var threads = GmailApp.getUserLabelByName("Label").getThreads();
And the function :
function readMail(){
var threads = GmailApp.getUserLabelByName("Label").getThreads();
var messages = GmailApp.getMessagesForThreads(threads);
for(var i in messages){
var message = messages[i];
for(var j in message){
var mess = message[j];
var sub = mess.getSubject();
if(mess.getTo().indexOf("email#gmail.com") > -1)
continue;
var attach = mess.getAttachments()[0];
var file = {
title: attach.getName()
};
var fileDoc = Drive.Files.insert(file, attach, {convert: false}); // Use Drive API
mess.markRead();
}
}
}
I'm trying to utilize the momentjs library in Google Apps Script but I'm not clear on how to do so. I'm not sure how to add the library, so obviously running something like the following results in "Reference Error: 'moment' is not defined":
var a = moment([2007, 0, 29]);
var b = moment([2007, 0, 28]);
var difference = a.diff(b);
Most people try to use the library with the key ending in 48. That library is pretty dated (it is version 2.9 which is pretty old).
Using eval and UrlFetchApp.fetch moment.js or any other external library can be used easily in google app scripts.
function testMoment() {
eval(UrlFetchApp.fetch('https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js').getContentText());
var date = moment().format("MMM Do YY");
Logger.log(date)
}
You may either host the moment.js on your own server, or use a CDN like cloudflare CDN to reference the library.
For cloudflare, here is the page which shows moment.js versions and their urls:
https://cdnjs.com/libraries/moment.js/
As of writing this post 2.18.1 is the latest version.
For the example posted by OP it will look like this:
function testMomentDifference() {
eval(UrlFetchApp.fetch('https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js').getContentText());
var a = moment([2007, 0, 29]);
var b = moment([2007, 0, 28]);
var difference = a.diff(b);
Logger.log(difference);
}
The moment script ID for the Google Apps Script IDE has changed. It is now "15hgNOjKHUG4UtyZl9clqBbl23sDvWMS8pfDJOyIapZk5RBqwL3i-rlCo"
You can add moment and moment.tz to app scripts by creating a new Script file and adding the following code:
var cacheExpire = 3600;
var momentCache = "momentCache";
var momentUrl = "https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.1/moment.min.js"
var momentTzCache = "momentTzCache";
var momentTzUrl = "https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.16/moment-timezone-with-data-2012-2022.min.js"
useCachedOrLive(momentCache,momentUrl);
useCachedOrLive(momentTzCache,momentTzUrl);
function useCachedOrLive(cacheToCheck, url){
var cache = CacheService.getUserCache();
var cachedData = cache.get(cacheToCheck);
console.log(cacheToCheck);
if(cachedData !== null){
console.log("using cached " + cacheToCheck)
eval(cachedData);
}
else
{
console.log("getting live " + cacheToCheck);
var response = UrlFetchApp.fetch(url).getContentText();
cache.put(cacheToCheck, response, cacheExpire);
eval(response);
}
}
This uses the cache service to reduce round trip calls and you can modify it to include a subset of data if you want.
Thanks to apadana for getting me started!
There is a better and best way to use moment
Do not use UrlFetchApp, to avoid quota exceeded, caching, and server issues
Download moment.min.js and momemt-timzone.min.js in last versions
and integrate the full files in apps script like the below screen
There is no problems in long run with this approach, just update the files any time when you need.
After adding the two files, just publish a new version and include it in any other script
For example:
I will create a script with name "MomentAPI" and include the two
files mentioned, and publish a new version.
in other script with name "myScript" I will include the library
"MomentAPI" with its script id as known
then will use it like the below examples
const moment = MomentAPI.moment; // init the library
const start = moment().startOf('day').toDate(); // Dec 06 00:00:00
const end = moment().endOf('day').toDate(); // Dec 06 23:59:59
const d = moment(1767139200000).tz('America/New_York').format('ha'); // 7am EST
Using external Javascript library is not so easy... Depending on the context in which you want to use it (a webapp of a document embedded script) the approach will be different.
I didn't try it in client JavaScript and I'm not sure caja will allow it but I found this post that shows a possible way to include it using a Google Script Library that a user has build and if I read the post it seems to work...
The "user" is a Google developper so he knows for sure what he is talking about ;) please update here if it worked for you.