Automating Google Analytics Data into Google Sheets
I want to automate a report where we want to add 200 rows of data into a spreadsheet, the data in these 200 rows comes from Google Analytics with each row having different filters, views etc. Please tell me how to do it?
do you know?
how many words do you know
See also questions close to this topic
-
PERCENTILE IF using ARRAYFORMULA for a set of conditions
I need to calculate the percentile using an if condition to calculate it by group of conditions, but Google Sheets doesn't provide PERCENTILEIF function. A nonarray solution is possible:
=ARRAYFORMULA(PERCENTILE(if(range=value,values),percentile))
but in my case
value
should be an array of possible values.Here is the sample data with the expected result highlighted:
I tried several options to use an array of possible values, but in all cases, I get the wrong result:
Using
JOIN
inG2
:=arrayformula(if(len(E2:E3),percentile(split(regexreplace(join(",", Arrayformula(A2:A12 & "_" & B2:B12)),E2:E3 & "_(\d+)|.",",$1"),","),D2),))
Using
MATCH
inH2
:=ARRAYFORMULA(if(len(E2:E3), PERCENTILE(IFNA(--(match(A2:A12,E2:E3,0) > 0) * B2:B12,),D2),))
here is the Spreadsheet file: https://docs.google.com/spreadsheets/d/1VDJIYvmOC46DI_9u4zSEfmxSan5R5VKK772C_kP5rxA/edit?usp=sharing
-
How do I show Popup Message everytime I go to another Sheet using Google Sheet/Apps Script?
I have 3 sheets in a workbook - Sheet1, Sheet2, and Sheet3, every time I change to a Sheet there is a Popup message that will show up.
What I had in mind...
function onOpen() { var ui = SpreadsheetApp.getUi(); ui.alert('This is my pop up message!'); }
-
Move row to a different sheet when box is checked
Hi I'm very new to coding with Google Sheets and Excel. My goal is to move a row when it is checked off.
The original sheet is called "School Assignments" and the sheet I want to move it to is called "Finished". When a box in column H (column 8) is checked the data value of the row becomes "Done". When it is not marked it is "Unfinished".
I want the row to move to the Finished sheet when I mark it as "Done". I also want this to work vice versa where when I uncheck and it becomes "Unfinished" it it goes back to the School Assignments sheet. I have some code but honestly it was done months ago (I'm coming back to this project after a break) and I'm not sure what I was thinking when I wrote it or if it is correct at all. It doesn't work obviously.
if(sh.getName() == "School Assignments" && e.range.columnStart == 8 && e.value == "Done") { let tsh = e.source.getSheetByName("Finished"); sh.getRange(e.range.rowStart, 1, 1, sh.getLastColumn()).moveTo(tsh.getRange(tsh.getLastRow() + 1, 1)); sh.deleteRow(e.range.rowStart); } else if(sh.getName() == "Finished" && e.range.columnStart == 8 && e.value == "Unfinished") { let tsh = e.source.getSheetByName("School Assignments"); let trg = tsh.getRange(tsh.getLastRow() + 1, 1); sh.getRange(e.range.rowStart, 1, 1, sh.getLastColumn()).moveTo(trg); sh.deleteRow(e.range.rowStart); } }
I also have an auto-sorting piece earlier in the code which defines some constants.
const ss = SpreadsheetApp.getActiveSpreadsheet() const ws = ss.getSheetByName("School Assignments") const range = ws.getRange(2,1,ws.getLastRow()-1,8) range.sort({column: 7, ascending: true }) }
I am totally unsure how to fix this and accomplish what I'm looking to do.
-
Output the Tuesday 6 weeks in the future in Python?
UPDATE: post edited to add answer to end of post
Core Question
Using Python, how do I output the date of the Tuesday that occurs 6 weeks after a certain date range?
Context
I work at a SaaS company in a customer facing role. Whenever I do an implementation for a client, the client receives a survey email on the Tuesday that occurs in the 6th week after our initial interaction.
To know which Tuesday to be extra nice on, we currently have to reference a chart that says if the interaction falls in date range x, then the client receives their survey solicitation on Tuesday y.
An example of this would be: if the interaction happened sometime within Apr. 18 - Apr. 22, then the survey goes out on May 31.
I would prefer for this to be done without having to hard code the date ranges and their corresponding Tuesdays into my program (just because I'm lazy and don't want to update the dates manually as the months go by), but I'm open to that solution if that's how it has to be. :)
Code Attempt
I can use datetime to output a particular date x weeks from today's date, but I'm not sure how to get from here to what I want to do.
import time from datetime import datetime, timedelta time1 = (time.strftime("%m/%d/%Y")) #current date time2 = ((datetime.now() + timedelta(weeks=6)).strftime('%m/%d/%Y')) #current date + six weeks print(time1) print((datetime.now() + timedelta(weeks=6)).strftime('%m/%d/%Y'))
Disclaimer: I am a beginner and although I did search for an answer to this question before posting, I may not have known the right terms to use. If this is a duplicate question, I would be thrilled to be pointed in the right direction. :)
~~~UPDATED ANSWER~~~
Thanks to @Mandias for getting me on the right track. I was able to use week numbers to achieve my desired result.
from datetime import datetime, timedelta, date today = date.today() #get today's date todays_week = today.isocalendar()[1] #get the current week number based on today's date survey_week = todays_week + 6 #add 6 weeks to the current week number todays_year = int(today.strftime("%Y")) #get today's calendar year and turn it from a str to an int survey_week_tuesday = date.fromisocalendar(todays_year, survey_week, 2) #(year, week, day of week) 2 is for Tuesday print("Current Week Number:") print(todays_week) print("Current Week Number + 6 Weeks:") print(todays_week + 6) print("Today's Year:") print(todays_year) print("The Tuesday on the 6th week from the current week (i.e. survey tuesday):") print(survey_week_tuesday.strftime('%m-%d-%Y')) #using strftime to format the survey date into MM-DD-YYYY format because that's what we use here even though DD-MM-YYYY makes more sense
-
insert bulk documents into mongo db
I need to insert multiple docs into mongo db at once. cannot directly import a csv file or use insertMany since there are nested objects inside each document. for outer object, one key's value will change every time while the rest of the key's value remain the same and need to generate random values for two of the other keys. for inner object, values change every time. this seems complicated to me and if anyone could help me breakdown the problem statement and help me automate it to avoid the tedious manual work, it'd be very helpful. I'm using Studio 3T and node.js to code.
{ "_id" : ObjectId("626f6f7b4199350845746a54"), "isApproved" : false, "msgStatus" : false, "name" : "IN", "createdBy" : "BAA0704", "customerId" : "HH00012", "villageId" : "1848", "ans" : { "responseID" : "5f440bc3-c76c-411a-b1e4-6a25a5f2aba3", "submittedTime" : "31-03-2022 16:45", "syncedTime" : "31-03-2022 16:45", "formRevisionSubmittedIn" : "2", "tags" : "NA", "timeSpent" : "0:16:12", "name" : "shruthi", "villagePopulation" : "10000", "age" : "28", "bankAccount" : "yes", "familyMembers" : "7", "maritalStatusYes" : "Yes", "maritalStatusNo" : "No", "kids" : "3", "socialMediaHandles" : "facebook" }, "createdAt" : ISODate("2022-05-02T13:22:19.630+0000"), "updatedAt" : ISODate("2022-05-02T13:22:19.630+0000"), "__v" : NumberInt(4325), "nId" : NumberInt(11)
-
CFG of w != w^R
Given
L={w in {a,b}* | w != w^R}
I want to find its CFG. Please do not tell me the answer for that.
What is the intuition of solving these kind of questions?
I tried doing it for about 1 hour, with no luck.
Thanks!
-
How would you capture a discount that covers the cost of taxes with GA4 Purchase parameters?
Would I add a data layer variable for the purchase event outside of the items array? This is Google's recommendation for purchase events. I want to add a coupon code with a discount that covers the entire cost including taxes. This is what google has in their doc:
dataLayer.push({ event: "purchase", ecommerce: { transaction_id: "T_12345", affiliation: "Google Merchandise Store", value: 25.42, tax: 4.90, shipping: 0, currency: "USD", coupon: "SUMMER_SALE", items: [ { item_id: "SKU_12345", item_name: "Stan and Friends Tee", affiliation: "Google Merchandise Store", coupon: "SUMMER_FUN", currency: "USD", discount: 2.22, index: 0, item_brand: "Google", item_category: "Apparel", item_category2: "Adult", item_category3: "Shirts", item_category4: "Crew", item_category5: "Short sleeve", item_list_id: "related_products", item_list_name: "Related Products", item_variant: "green", location_id: "L_12345", price: 9.99, quantity: 1 }] } });
I want to create a cart that gives the user for free. Or rather a $0 cart value. Would I add the coupon discount ($4.90 = value + tax) for the whole cart like this:
dataLayer.push({ event: "purchase", ecommerce: { transaction_id: "T_12345", affiliation: "Google Merchandise Store", value: 0, tax: 4.90, shipping: 0, currency: "USD", coupon: "SUMMER_SALE", discount: 4.90, items: [ { item_id: "SKU_12345", item_name: "Stan and Friends Tee", affiliation: "Google Merchandise Store", coupon: "SUMMER_FUN", currency: "USD", discount: 9.99, index: 0, item_brand: "Google", item_category: "Apparel", item_category2: "Adult", item_category3: "Shirts", item_category4: "Crew", item_category5: "Short sleeve", item_list_id: "related_products", item_list_name: "Related Products", item_variant: "green", location_id: "L_12345", price: 9.99, quantity: 1 }] } });
Or would the discount amount including tax ($14.69 = intended discount for product + cost of tax) also be included in the discount for the item in the items array.
dataLayer.push({ event: "purchase", ecommerce: { transaction_id: "T_12345", affiliation: "Google Merchandise Store", value: 0, tax: 4.90, shipping: 0, currency: "USD", coupon: "SUMMER_SALE", discount: 4.90, items: [ { item_id: "SKU_12345", item_name: "Stan and Friends Tee", affiliation: "Google Merchandise Store", coupon: "SUMMER_FUN", currency: "USD", discount: 14.69, index: 0, item_brand: "Google", item_category: "Apparel", item_category2: "Adult", item_category3: "Shirts", item_category4: "Crew", item_category5: "Short sleeve", item_list_id: "related_products", item_list_name: "Related Products", item_variant: "green", location_id: "L_12345", price: 9.99, quantity: 1 }] } });
This is the doc from google that I've been referencing.
Thanks for your help!
-
Adding an custom event to GTM Vimeo event tracking
I'm using this script to push play/pause/progress of vimeo videos on our website. I'd like to push another event "load" when video is loaded on page. I've tried adding a part to send info to the data layer when the video is ready as such:
function onReady(data) { try{ //push to data layer load dataLayer.push({ event: "video", video_action: "load", video_url: 'https://vimeo.com/' + getLabel(data.player_id), video_percent: data.data.percent.toFixed(2) * 100, video_title: _playerTitle[getLabel(data.player_id)].toLowerCase() }); } catch(err){ } }
Here is the full script which pushes the rest of the data sucessfuly.
<!-- Google Analytics Tag Manager (V2) custom HTML tag for Vimeo video tracking Copyright 2016, Cardinal Path, Inc. Original author: Bill Tripple <btripple@cardinalpath.com> Revised by: Bogdan Bistriceanu <bbistriceanu@cardinalpath.com> Version 2.0 --> <script> var dataLayer = (typeof(dataLayer) !== "undefined" && dataLayer instanceof Array) ? dataLayer : []; var videoLabels=[]; var lastP=[]; //we declare variables that will hold information about the video being played var _playerTitle = {}, _playerAuthor = {}, _playerAuthorURL = {}, _playerUploadDate = {}; try{ init(); } catch(err){ dataLayer.push({ 'event': 'gtm.error', 'errorMessage': e.message, 'tag': 'CP - UA - Vimeo Video Listener' }) } function init(){ try{ var player=document.getElementsByTagName("iframe"); for (i = 0; i < player.length; ++i) { var url=player[i].getAttribute("src"); if(/player\.vimeo\.com\/video/.test(url)){ // vimeo iframe found if(!player[i].hasAttribute("id")){ // id attribute missing player[i].setAttribute("id","vimeo_id_"+i); // add id attribute } var urlUpdated=false; if(!/api=/.test(url)){ // check to see if api parameter is in src attribute url=updateUrl(url,"api",1); urlUpdated=true; } if(!/player_id=/.test(url)){ // check if player_id is in src attribute url=updateUrl(url,"player_id",player[i].getAttribute("id")); urlUpdated=true; } if(urlUpdated){ // repopulate src attribute with added parameters player[i].setAttribute("src",url) } videoLabels[player[i].getAttribute("id")]=player[i].getAttribute("src"); // id to label dictionary } } // Listen for messages from the player if (window.addEventListener){ window.addEventListener('message', onMessageReceived, false); } else { window.attachEvent('onmessage', onMessageReceived, false); } } catch(err){ } } function updateUrl(url,param,value){ try{ return url+((/\?/.test(url)) ? "&" : "?")+param+"="+value; } catch(err){ } } // Handle messages received from the player function onMessageReceived(e) { try{ var data = e.data; if(typeof data === "string"){ data = JSON.parse(data); } switch (data.event) { case 'ready': onReady(data); break; case 'play': onPlay(data); break; case 'pause': onPause(data); break; case 'playProgress': onPlayProgress(data); break; } } catch(err){ } } // Helper function for sending a message to the player function post(action, value) { try{ var data = { method: action }; if (value) { data.value = value; } var message = JSON.stringify(data); var player = document.getElementsByTagName("iframe"); var url; var prot; for (i = 0; i < player.length; ++i) { url=player[i].getAttribute("src"); if(/player\.vimeo\.com\/video/.test(url)){ // Check if protocol exists prot = player[i].getAttribute('src').split('?')[0].split('//')[0]; // If protocol doesn't exist, then need to append to "url" if (!prot){ url="https:" + player[i].getAttribute("src").split('?')[0]; } player[i].contentWindow.postMessage(data, url); } } } catch(err){ } } function getLabel(id){ try{ return videoLabels[id].split('?')[0].split('/').pop(); } catch(err){ } } //our function that will use the Vimeo oEmbed API to retrieve additional information about the video function getVimeoInfo(url, callback) { var script = document.createElement('script'); script.type = 'text/javascript'; script.src = url; document.getElementsByTagName('body')[0].appendChild(script); } //the callback function which takes the data received from the Vimeo oEmbed API and places it into the corresponding objectes function vimeoCallback(e){ //console.log(e); _playerTitle[e['video_id']] = e['title']; _playerAuthor[e['video_id']] = e['author_name'] _playerAuthorURL[e['video_id']] = e['author_url'] _playerUploadDate[e['video_id']] = e['upload_date'] } function onReady(data) { try{ //execute our function which queries the Vimeo oEmbed API once the embedded videos are "ready" getVimeoInfo("https://www.vimeo.com/api/oembed.json?url=https://vimeo.com/"+getLabel(data.player_id)+"&callback=vimeoCallback", vimeoCallback); post('addEventListener', 'play'); post('addEventListener', 'pause'); post('addEventListener', 'finish'); post('addEventListener', 'playProgress'); } catch(err){ } } function onPlay(data){ try{ dataLayer.push({ event: "vimeo", eventCategory: "vimeo", eventAction: "vimeo play", eventLabel: _playerTitle[getLabel(data.player_id)].toLowerCase() + " - " + getLabel(data.player_id), vimeo_playerID: getLabel(data.player_id), vimeo_playerTitle: _playerTitle[getLabel(data.player_id)].toLowerCase(), vimeo_playerAuthor: _playerAuthor[getLabel(data.player_id)].toLowerCase(), vimeo_playerAuthorURL: _playerAuthorURL[getLabel(data.player_id)].toLowerCase(), vimeo_playerUploadDate: _playerUploadDate[getLabel(data.player_id)], nonInteractive: true }); } catch(err){ } } function onPause(data){ try{ dataLayer.push({ event: "vimeo", eventCategory: "vimeo", eventAction: "vimeo video pause", eventLabel: _playerTitle[getLabel(data.player_id)].toLowerCase() + " - " + getLabel(data.player_id), vimeo_playerID: getLabel(data.player_id), vimeo_playerTitle: _playerTitle[getLabel(data.player_id)].toLowerCase(), vimeo_playerAuthor: _playerAuthor[getLabel(data.player_id)].toLowerCase(), vimeo_playerAuthorURL: _playerAuthorURL[getLabel(data.player_id)].toLowerCase(), vimeo_playerUploadDate: _playerUploadDate[getLabel(data.player_id)], nonInteractive: true }); } catch(err){ } } // Track progress: 25%, 50%, 75%, 100% function onPlayProgress(data) { try{ var t = data.data.duration - data.data.seconds <= 1.5 ? 1 : (Math.floor(data.data.seconds / data.data.duration * 4) / 4).toFixed(2); if (!lastP[data.player_id] || t > lastP[data.player_id]) { lastP[data.player_id]=t; if (parseFloat(t) != 0){ dataLayer.push({ event: "vimeo", eventCategory: "vimeo", eventAction: "vimeo video " +t*100+ "% Complete", eventLabel: _playerTitle[getLabel(data.player_id)].toLowerCase() + " - " + getLabel(data.player_id), vimeo_playerID: getLabel(data.player_id), vimeo_playerTitle: _playerTitle[getLabel(data.player_id)].toLowerCase(), vimeo_playerAuthor: _playerAuthor[getLabel(data.player_id)].toLowerCase(), vimeo_playerAuthorURL: _playerAuthorURL[getLabel(data.player_id)].toLowerCase(), vimeo_playerUploadDate: _playerUploadDate[getLabel(data.player_id)], nonInteractive: true }) } } } catch(err){ } } </script>
-
Appending one row at a time from Dataframe to Google Sheet with Python
I have this code for writing data to google sheets with Python. Is it possible to append one row at a time, instead of inserting the entire data frame at once?
sheet = service.spreadsheets() result = sheet.values().get(spreadsheetId=os.environ['GOOGLE_SHEET_ID'], range=range, valueRenderOption='FORMATTED_VALUE').execute() new_row = df.applymap(str).values.tolist() result = sheet.values().append( spreadsheetId=os.environ['GOOGLE_SHEET_ID'], range=range, valueInputOption='USER_ENTERED', body=dict( majorDimension='ROWS', values=new_row) ).execute()
-
Google Sheet App Script: Match 1 values from one sheet to another sheet and then if condition met set background
I'm new to app script and still learning how to do thing. Here's what I want to do: I have 2 sheets, in the 1st are just the names ('List') in columns based on each person language, the 2nd one is schedule ('Roster'). I want to change cell background into green the cell with person name when person is on schedule from 8-5.
Any help or idea is very appreciated. Thank you in advance.
Here's what I tried so far to do:
function addShiftColor() { var ss = SpreadsheetApp.getActiveSpreadsheet(); var actSheet = ss.getSheetByName('List'); var rosSheet = ss.getSheetByName('Roster'); var lastCol = actSheet.getLastColumn() +1; var lastRow = actSheet.getLastRow() +1; var end = rosSheet.getLastRow(); for (var column = 1; column < lastCol; column++) { for (var row = 1; row < lastRow; row++) { var cellget = actSheet.getRange(row, column).getValue(); var cellset = actSheet.getRange(row, column); for(i=1, j=5; i <= end, j <= end; i++,j++){ var cell1 = rosSheet.getRange(i, 1).getValue(); var cell2 = rosSheet.getRange(j, 253).getValue(); if(cell1 === cellget && cell2 === "08 -- 17"){ cellset.setBackground("green"); } } } } }
This is the result I want to achieve.
Here is the link to the file https://docs.google.com/spreadsheets/d/1wfSEQtqZJ3XEPla_KRBp7v56sPV5wlciHEHA7IS0MaI/edit?usp=sharing
Thank you!
-
gapi.analytics.auth authorize change access_token doesn't work
in the code, I'm using gapi.analytics.auth.authorize function with access_token as shown below:
gapi.analytics.auth.authorize({ serverAuth: { access_token: access_token_one } });
after that, I'm displaying DataChart:
timeline = new gapi.analytics.googleCharts.DataChart({ ... }); this.timeline.execute();
the problem is that when I change the access_token for another user:
gapi.analytics.auth.authorize({ serverAuth: { access_token: access_token_two } });
and do again
this.timeline.execute()
- it uses old, previous access_token (access_token_one instead of access_token_two), so that the access_token is not changed. -
Grpc.Core.Internal.CoreErrorDetailException: Failed to pick subchannel
I have this following error (sometimes) when I call the Google Analytics Data API v1 by a .NET application :
Unhandled Exception: , DebugException="Grpc.Core.Internal.CoreErrorDetailException: {"created":"@1651830843.560000000","description":"Failed to pick subchannel","file":"......\src\core\ext\filters\client_channel\client_channel.cc","file_line":3159,"referenced_errors":[{"created":"@1651830843.560000000","description":"failed to connect to all addresses","file":"......\src\core\lib\transport\error_utils.cc","file_line":147,"grpc_status":14}]}") at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Grpc.Core.Internal.AsyncCall
2.UnaryCall(TRequest msg) at Grpc.Core.Calls.BlockingUnaryCall[TRequest,TResponse](CallInvocationDetails
2 call, TRequest req) at Grpc.Core.DefaultCallInvoker.BlockingUnaryCall[TRequest,TResponse](Method2 method, String host, CallOptions options, TRequest request) at Grpc.Core.Interceptors.InterceptingCallInvoker.<BlockingUnaryCall>b__3_0[TRequest,TResponse](TRequest req, ClientInterceptorContext
2 ctx) at Grpc.Core.ClientBase.ClientBaseConfiguration.ClientBaseConfigurationInterceptor.BlockingUnaryCall[TRequest,TResponse](TRequest request, ClientInterceptorContext2 context, BlockingUnaryCallContinuation
2 continuation) at Grpc.Core.Interceptors.InterceptingCallInvoker.BlockingUnaryCall[TRequest,TResponse](Method2 method, String host, CallOptions options, TRequest request) at Google.Analytics.Data.V1Beta.BetaAnalyticsData.BetaAnalyticsDataClient.RunReport(RunReportRequest request, CallOptions options) at Google.Api.Gax.Grpc.ApiCall.GrpcCallAdapter
2.CallSync(TRequest request, CallSettings callSettings) at Google.Api.Gax.Grpc.ApiCallRetryExtensions.<>c__DisplayClass1_02.<WithRetry>b__0(TRequest request, CallSettings callSettings) at Google.Api.Gax.Grpc.ApiCall
2.<>c__DisplayClass10_0.b__1(TRequest req, CallSettings cs) at Google.Api.Gax.Grpc.ApiCall`2.Sync(TRequest request, CallSettings perCallCallSettings) at Google.Analytics.Data.V1Beta.BetaAnalyticsDataClientImpl.RunReport(RunReportRequest request, CallSettings callSettings) at CAC_Occitanie.Program.RunMyReport(String datedebut, String datefin) in C:\Users\sp_farmadmin\source\repos\1-IMAGE\CAC_Occitanie\CAC_Occitanie\Program.cs:line 62 at CAC_Occitanie.Program.Main(String[] args) in C:\Users\sp_farmadmin\source\repos\1-IMAGE\CAC_Occitanie\CAC_Occitanie\Program.cs:line 78The environment variable GOOGLE_APPLICATION_CREDENTIALS is set.
Thank you for helping me