Wait until response from API to execute javascript Function - javascript

I have a site which shows the weather for the next three days of a previously specified city (default city or city searched using a form) --> http://agustin-suarez.com/demos/yield/index.html
I use the API of OpenWeatherMap.org to do so. I am also using Google Tag Manager to send some events to Google Analytics which save the results obtained in the website. This is the code for the Macro (custom html tag):
<script>
(function($) {
$(window).bind("load", function() {
var climaMañana = document.getElementById("reservar1Clima").value;
var precioMañana = document.getElementById("reservar1Precio").value;
var climaPasadoMañana = document.getElementById("reservar2Clima").value;
var precioPasadoMañana = document.getElementById("reservar2Precio").value;
var climaDosDias = document.getElementById("reservar3Clima").value;
var precioDosDias = document.getElementById("reservar3Precio").value;
dataLayer.push({'event': 'climaMañana', 'eventLabelMañana': climaMañana, 'eventValueMañana': precioMañana});
dataLayer.push({'event': 'climaPasadoMañana', 'eventLabelPasadoMañana': climaPasadoMañana, 'eventValuePasadoMañana': precioPasadoMañana});
dataLayer.push({'event': 'climaDosDias', 'eventLabelDosDias': climaDosDias, 'eventValueDosDias': precioDosDias});
});
})(jQuery);
</script>
It works really good 90% of the time, but if the API spends more time than usual to send the response, Google Tag Manager is sending those events anyway with blank values for the variables, which is not optimal for keeping data quality in Google Analytics.
Any suggestion for making Google Tag Manager to wait until all variables are populated?

Related

Container-bound Apps Script does not execute properly from change to Google Sheet under certain circumstances

I have a container-bound script that reads data from a Google Sheet (its container), creates an event in a Google Calendar and then updates the Google Sheet with a confirmation to say that it has created a calendar event. The script is triggered to execute every time there is a change to the spreadsheet.
During testing, the script works perfectly as it should. However, when data is automatically entered into the Google Sheet from a Google Form (followed by some changes made through a Google Forms add-on), the script executes but does not update the Sheet with the confirmation of a new calendar event. This then results in the script creating duplicate calendar events because it does not see the confirmation in the Google Sheet.
Here is an excerpt of my Google Sheet data:
Google Sheet data for employee leave details
And below is my script:
function synctocalendar() {
var spreadsheet = SpreadsheetApp.getActiveSheet();
var calendarId = spreadsheet.getRange("Calendar_sync!H2").getValue();
var eventCal = CalendarApp.getCalendarById(calendarId);
var submissions = spreadsheet.getRange("Calendar_sync!A2:F").getValues();
var last = submissions.length-1
for (x=last; x>0; x--) {
var shift = submissions[x];
var startTime = shift[2];
var endTime = shift[3];
var title = shift[0]+" | "+shift[1];
var ssr = x+2
if (shift[4]!=="" && shift[4]!=="Complete" && shift[4]!=="Declined" && shift[4]!=="In progress") {
break
} else if (shift[4]=="Complete" && shift[5]!=="Y" && shift[5]!=="N") {
eventCal.createEvent(title, startTime, endTime);
var endf = spreadsheet.getRange(ssr,6)
endf.setValue("Y")
break
}
}
}
When I run the script directly from the editor it works perfectly. It reads the data, creates a calendar event, then returns a "Y" in column F (provided it satisfies the IF criteria).
When I have a trigger set to run the script whenever a change is made to the sheet, I can again get the script to run as I expect by manually deleting the "Y" from column F in any one of the rows.
However, when a new submission is written to the Google Sheet from a Google Form (followed by some spreadsheet changes made from a Google Forms add-on for approvals), the script still runs and still creates a calendar event, but does not write a "Y" back into the sheet.
EDIT: Details on the Google Forms add-on
The add-on sends emails on form submission with the form data to be approved. Once the recipient of the email approves the data from the Google Form, the add-on makes changes to the spreadsheet to reflect that.
i.e. when a form is submitted, column E in the spreadsheet will say "In Progress" and once the approval process is complete, the add-on will change column E to say "Complete". At this point, the script recognises it is complete and creates a calendar event.

Google Script in New Google Site Menu: How to?

I am trying to "install" a Google script as a menu item in a Google Site (a new Google Site--not the "Classic Google Site").
This script is supposed to add a new line to a spreadsheet that is embedded in the Site. That spreadsheet (named "Catalog") is a Google Sheet and the script (I want to run from the Google Site) is already installed as a bound script in the Sheet and works when toggled from the S
heet.
The script essentially adds a new line at the bottom of my song catalog to create a new line to add a new song.
The script that is working in the spreadsheet is:
function addSong() {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getActiveSheet();
var numRows = sheet.getLastRow()
sheet.appendRow([numRows+1]);
}
My problem is I do not know how to access the script from the site. I.e., I do not know how to reference the script in the site menu (by URL or what?) to get it to run.
The way I envision it working is that I have a sub-page under my "Catalog" menu in the site called "Add Song" and when I toggle it, I want the script to run and add a line to the Catalog Sheet.
Any help?
Updated with a cleaner example:
Firstly, the best way to access your GAS script from elsewhere is probably to publish it as a Web App. That way the script can be called via its published URL. The main requirement for a Web App is that it has a doGet() function as an entry point.
I'm pretty sure that you can only associate a new Google Sites menu item with another page within the same site. So you can’t invoke the WebApp (via it's URL) directly from a menu. But on that new Sites page the menu item takes you to, you can either:
associate a Sites button with the Web App URL (if that helps), or
embed some HTML code with JavaScript in the page that is invoked when the page is loaded; a bit more complicated, but it does mean the call to the Web App would be automated.
The code below is a simple web app, which is a bound function within a sheet. If you publish this (Publish >> Deploy as a WebApp...) and then grab the url you can associate this with a button or call from the page.
function doGet(request){
addSong(request.parameter.song); // Call your own function.
var response = {status: "SUCCESS", data: request.parameter.song};
// Return the response.
return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON);
}
function addSong(song) {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getActiveSheet();
var numRows = sheet.getLastRow()
sheet.appendRow([numRows+1,song]);
}
To use a button add the following as a link with the button:
https://script.google.com/macros/s/<your web app ref>/exec?song=%22Bohemian%20Rhapsody%22
The code below is an example of automatically calling the WebApp from embedded HTML in the Sites web page accessed via the menu. There are other ways of invoking the Web App from JavaScript, but XMLHttpRequest() works with most browsers.
<!DOCTYPE html>
<html>
<body onload="test('https://script.google.com/macros/s/<your web app ref>/exec?song=StairwaytoHeaven') ;">
<p id="message">? </p>
<script>
function test(url) {
var XHR = new XMLHttpRequest();
XHR.onreadystatechange = function() {
if(XHR.readyState == 4) {
if(XHR.status == 200) {
console.log("SUCCESS: status = "+XHR.status);
document.getElementById("message").innerHTML = XHR.responseText;
console.log(XHR.responseText);
} else {
console.log("FAILURE: status = "+XHR.readystate+" "+XHR.status);
document.getElementById("message").innerHTML = "Failure";
}
}
}
XHR.open("GET", url + ((/\?/).test(url) ? "&" : "?") + Date.now()); // Add timestamp to disable caching, if required.
XHR.send();
return;
}
</script>
</body>
</html>

How to get JS script of a Google form?

I owned a google form, how can I get the js script of it?
I click the Script Editor but there is no corresponding js I can find.
I have already searched on internet but no expected answers.
--
update on 20/08/2017
Assume that I owned a form like this :
Sample Form.
How can I get the corresponding google script of this form?
i.e.,
function myFunction() {
// Create a new form, then add a checkbox question, a multiple choice question,
// a page break, then a date question and a grid of questions.
var form = FormApp.create('Sample Form');
var sect1 = form.addSectionHeaderItem();
var item = form.addCheckboxItem();
item.setTitle('What condiments would you like on your hot dog?');
item.setChoices([item.createChoice('Ketchup'), item.createChoice('Mustard'), item.createChoice('Relish')]);
var item2 = form.addMultipleChoiceItem().setTitle('Do you prefer cats or dogs?');
// .setChoiceValues(['Cats','Dogs'])
// .showOtherOption(true);
var sect2 = form.addSectionHeaderItem();
form.addPageBreakItem().setTitle('Getting to know you');
form.addDateItem().setTitle('When were you born?');
var sect3 = form.addSectionHeaderItem();
var break2 = form.addPageBreakItem().setTitle('Getting to know you 2');
var choice1 = item2.createChoice('cat', FormApp.PageNavigationType.CONTINUE);
var choice2 = item2.createChoice('dog', break2);
item2.setChoices([choice1, choice2]);
form.addGridItem().setTitle('Rate your interests').setRows(['Cars', 'Computers', 'Celebrities']).setColumns(['Boring', 'So-so', 'Interesting']);
Logger.log('Published URL: ' + form.getPublishedUrl());
Logger.log('Editor URL: ' + form.getEditUrl());
}
Google Script Editor is a way that Google allows people to make their forms (and many other Google services) more flexible and customizable. You can even create Add-ons using Google Scripts. But there is not such thing as a default user script for each form; all forms begin with no user Google Scripts at all and it is up to you to add some more functionality by writing some new scripts.
Now, if you mean to get the javascript source of that form, then you can use Developer Tools in Chrome (F12 key in Windows) and go to sources, there you'll see all the cripts that Google uses for the forms:
And if you left click the form and view the source of it, you'll see some more small script blocks mostly related to the data that the Google Form has:
<script>_docs_flag_initialData={ ....
<script>;this.gbar_={CONFIG:[[[0,"www.gstatic.com", ....
<script type="text/javascript">var FB_PUBLIC_LOAD_DATA_ = [null,[null, ....
Another approach can be to create a html form yourself and send a request to a Google Apps Script Web app. See this example if you want to try it out: https://gist.github.com/mhawksey/1276293
Regards, Peter

How to write Jquery plugin for Google Analytics?

I would like to create a custom plugin for tracking events in my JavaScript Application using Google Analytics Measurement Tool (GA MT), but I am a newbie and not sure how to write such plugin.
My idea about the plugin:
it should have defined all types of events I am going to track (i.e. starting of an application, button clicked, 1st, 2nd, ... slide entered, etc)
if I understand how GA MT works correctly, I will need to specify an event hit for each custom event (see more)
part of the hit parameters (url) is shared (such as version, client ID, tracking ID...)
the other part of the url is custom, so I will store the differences in various functions inside of the plugin
these functions will be later called i.e. on button clicked, on goToNextSlide etc, which will send a hit to GA.
This is an example of my plugin:
(function( $ ) {
var $_document = $(document);
// Shared hit parameters
var hit = 'https://www.google-analytics.com/collect?';
hit += 'v=1'; // Version.
hit += '&t=pageview'; // Pageview hit type.
hit += '&tid=UA-XXXXXX-Y'; // Tracking ID / Property ID.
hit += '&cid=555'; // Client ID.
/* Application opened */
function gacAppOpened() {
console.log('gacAppOpened');
hit += '&dp=%2Fslide-1'; // Page.
httpGetRequest(hit);
}
/* Slide-2 entered */
function gacSlide2() {
console.log('gacSlide2');
hit += '&dp=%2Fslide-2'; // Page.
httpGetRequest(hit);
}
function httpGetRequest( theUrl )
{
var req = new XMLHttpRequest();
req.open("POST", theUrl, true);
req.send(null);
}
}( jQuery ));
This is how I load the plugin (gaCustom.js) and my common JS file (app.js)
<script src="js/gaCustom.js"></script>
<script src="js/app.js"></script>
When trying to reach to my function from inside app.js, I got error (not a function)
goToDefault: function() { // loads first page of my app,
// a hit should be sent to GA about app started
...
gacAppOpened();
... // render template
},
So I am wrong somehow in defining the plugin and using it. I also tried few other attempts, but all of them failed.
I would appreciate to hear whether my approach is good or wrong and what to improve as I am a newbie and would like to do this correctly.

Auto-refresh Javascript For RSS Using Google Feed API

I apologize if the title is trash. What I'd like to do is rather simple in concept... but I'm having a bit of trouble.
I would like to automatically refresh an RSS feed that is displayed using Google Feed API. I haven't worked with the Google Feed API before, but it seemed like a quick option for getting this rolled out. Technically, it only needs to be the content part that is reloaded.
The purpose: This is displaying the results of a poll, refreshing them every 3 seconds (it will be displayed in a presentation.) The actual result is in the 'content', whereas the item being voted on is the 'title'.
The unstyled basics of the code:
<script type="text/javascript">
var feedcontainer=document.getElementById("feeddiv");
var feedurl="http://theurl.com";
var feedlimit=100;
var rssoutput="<b>Latest Results:</b><br /><ul>";
function rssfeedsetup(){
var feedpointer=new google.feeds.Feed(feedurl) //Google Feed API method
feedpointer.setNumEntries(feedlimit) //Google Feed API method
feedpointer.load(displayfeed) //Google Feed API method
}
function displayfeed(result){
if (!result.error){
var thefeeds=result.feed.entries
for (var i=0; i<thefeeds.length; i++)
rssoutput+="<li>" + thefeeds[i].title + "<br />" + thefeeds[i].content + "</li>"
rssoutput+="</ul>"
feedcontainer.innerHTML=rssoutput
}
else
alert("Error fetching feeds!")
}
window.onload=function(){
rssfeedsetup()
}
</script>
I'm not sure how to go about making the results refresh every 3 seconds. I've tried a few things, like "How to autorefresh XML in Javascript" but wound up printing the results multiple times on the page.
Major bonus points for anyone that can point me towards turning it into an auto refreshing bar graph. That will be my next search or question on here.
I think you should call rssfeedsetup() in a setInterval function. Something like
window.onload = function() {
var delay = 3000;
rssfeedsetup();
setInterval(rssfeedsetup, delay);
}

Categories

Resources