I have created a script to go along with a camp signup form. When I student signs up, I need an email sent to both the parent and the leader. I have the general script format correct as each one works when by itself (the script is bound to the spreadsheet, not the form). But if I have both functions in the code.gs file or in a separate file, neither of them work. How are we supposed to run more than one function attached to a form submission?
Here is my code for the two emails to be sent:
Here is my code for the two emails to be sent (if I add both these, it doesn't work):
function emailResponseToParent(e) {
var studentName = e.values[1];
var parentEmail = e.values[3];
var tripName = e.values[6]
var subject = "Your Young Life " + tripName + " registration has been submitted."
var message = "We have received " + studentName + "'s signup registration for the " + tripName + ". More words here....";
MailApp.sendEmail(parentEmail, subject, message);
}
function emailResponseToLeader(e) {
var studentName = e.values[1];
var leaderEmail = "meg#me.com";
var tripName = e.values[6]
var subject = "A Young Life student of yours has signed up for " + tripName + " camp."
var message = studentName + "has just registered for " + tripName + ". More words here....";
MailApp.sendEmail(leaderEmail, subject, message);
}
A separate question (less important) is how to create a script so that a later follow up email goes out based on a date (e.g. the week before camp starts).
I don't know if this will be of any use but you can create a list of recipients to receive the SAME email (just like any email can specify multiple recipients). To do this replace your MailApp with the following:
var Emails = parentEmail + "," + leaderEmail;
MailApp.sendEmail(Emails, subject, message);
It has worked for me (but both recipients wanted the same info).
I couldn't get my script to access the form data until I came across the method used in your script (e.values[ ] ) which worked a treat - so thanks for that!
Related
I am trying to setup an email notification and my hope is to have a simple list of all the items in a datasource (separated into their fields).
Ex:
ItemName01, Cost01, Quantity01
ItemName02, Cost02, Quantity02
ItemName03, Cost03, Quantity03
Doing a projection of each (#datasources.Datasource.items..ItemName + #datasources.Datasource.items..Cost + #datasources.Datasource.items..Quantity) gives me everything, but not organized correctly.
Ex. [ItemName01,ItemName02,ItemName03],[Cost01,Cost02,Cost03],[Quantity01,Quantity02,Quantity03]
Any help/thoughts are appreciated.
Thanks!
I would recommend to use server script for this:
// query records
var records = app.models.Item.newQuery().run();
// generate email HTML body
var emailBody = records.reduce(function(str, item) {
str += '<p>' + item.Name + ', ' + item.Cost + ', ' + item.Quantity + '</p>'
});
// hand off generated HTML to other function
// that will actually send email
sendEmail(emailBody);
You can call this Server Script from Model Events or explicitly from client using google.script.run. You also can pass some filters to narrow records set to be sent.
I have button with ID on the website.
At the moment we track button click with Tag Manager and Analytics.
But I would like to know, is there a way to save information about user ID and time when button was clicked?
Looking forward for any information.
Thank you!
I guess user ID, what you mentioned is internal ID in your website. First of all, you need to find a way how to receive user ID in your system. It can be many ways.
For example, let's say that your website has hidden input with user ID which has id="user-id" and you want to track button "Track this button". Basic html code if your page is:
<input type="hidden" id="user-id" value="unqieuserid123"/>
<button id="button-id">Track this button</button>
You need to create user defined variable (Variables->User-Defined Variables->New). Choose "Javascript" and enter name "UserId" and this code:
function () {
return document.getElementById("user-id") != null ?
document.getElementById("user-id").value : ""
}
At the end it should be like that:
Create variable for receiving user time (it will write user local time) with name "UserTime" and javascript code:
function() {
// Get local time as ISO string with offset at the end
var now = new Date();
var tzo = -now.getTimezoneOffset();
var dif = tzo >= 0 ? '+' : '-';
var pad = function(num) {
var norm = Math.abs(Math.floor(num));
return (norm < 10 ? '0' : '') + norm;
};
return now.getFullYear()
+ '-' + pad(now.getMonth()+1)
+ '-' + pad(now.getDate())
+ 'T' + pad(now.getHours())
+ ':' + pad(now.getMinutes())
+ ':' + pad(now.getSeconds())
+ '.' + pad(now.getMilliseconds())
+ dif + pad(tzo / 60)
+ ':' + pad(tzo % 60);
}
At the end it should be like that:
Enable built-in variable Click Element if it is not enabled yet.
Create new trigger, for your button. In my case it is like that:
Create new tag for tracking and sending data to GA. Here you can use your variables created on step #1 and #2. Like {{UserId}} and {{UserTime}}. In my example it is like that:
At the end in Google Analytics you will receive event with this label:
'user id: unqieuserid123; user time: 2017-05-31T12:20:19.06+04:00'
I solved this problem in the following way:
- Created variables in Google Tag Manager (GTM) which track the user ID and the date & time.
I already had tags which tracked button clicks on the website, so I added these variables in the categories of Tags ("Label" and "Value")
Click event
Every time user click on the button, these variables track information about ID and date&time.
say, I have a huge records built up over the months,so which method to use?
1.Is there a speed different when the transactional record size is huge for the below?
2.If below not good. What method to use to search thru say more than 10 000 records which contain only customer details like name, addr, contact or others.
3.What is the record size that I should think about back up the existing database and re-create a new one after deleting the old one.
1) QueryAsync
var db = new SQLiteAsyncConnection(DBPath);
var allitems = await db.QueryAsync("Select * From Customer Where CompanyName ='" + Class1.Company + "'" + " AND No ='" + No + "'");
2) Non Async
var db = new SQLiteConnection(DBPath);
var allitems = db.Query("Select * From Customer Where CompanyName ='" + Class1.Company + "'" + " AND No ='" + No + "'");
You are fine using only Query. QueryAsync will probably not provide much, if any boost in performance.
10,000 records is not very many, so your query should be quick. If have not already, you can create an index on the Customer table, which will hugely speed up the query.
For example...
CREATE INDEX CompanyNameNo ON Customer (CompanyName, No)
Check out http://www.sqlite.org/lang_createindex.html for information on indexes.
Is it possible to use the Linkedin API to see new connections made by my (authenticated user) 1st degree connections?
Using a call like:
GET http://api.linkedin.com/v1/people-search?facet=network,S
I can search for second degree connections. However, the goal is to get new connections of selected 1st degree connections.
Any help much appreciated.
You can get new connection with using this URL
http://api.linkedin.com/v1/people/~/connections?modified=new&modified-since=1267401600000
Where modified-since is the time you last made the request.
you can check more detail here https://developer.linkedin.com/documents/connections-api
I think Linkedin Change URL : New URL is :
https://developer-programs.linkedin.com/documents/connections-api
Yes. It's quite easy to see other people or your connections using the following code I wrote. If you want to search for other people's new connection, simply replace the 'Me' with other people's id.
//Function that displays the member's updates:
function onLinkedInAuth() {
IN.API.MemberUpdates("me")
.params({"type": "CONN", "count": 1}) // get the five most-recent Shares for the viewer and EjDUWNoC3C
.result(displayNetworkUpdates)
.error(displayNetworkUpdatesError);
}
//Note: You can only see your friend's most recent connection
function displayNetworkUpdates(updates) {
var profileDiv = document.getElementById("networkupdates");
var conns = updates.values[0].updateContent.person.connections; // the person sharing content
var man = conns.values[0];
profileDiv.innerHTML += "<p>" + man.firstName + " " + man.lastName +".</p>";
}
See when I look for people/my new connection, I only ask for 1. This is because LinkedIn API is not generous enough to grant more privilege. They ONLY ALLOW US TO VIEW 1 CONNECTION/ most recent connection.
Also, just so you know, find your friend's id is quite easy as well. Just search for connections of yours using the following code, then you can obtain a list of your connections and their IDs.
//Functions that displays users' connections
function onLinkedInAuth() {
IN.API.Connections("me")
.fields("firstName", "lastName", "industry", "id")
.params({"start": 10, "count": 5}) // start begins at 0
.result(displayConnections)
.error(displayConnectionsErrors);
}
function displayConnections(connections) {
var connectionsDiv = document.getElementById("connections");
var start = connections._start + 1; // because humans count from 1, not 0.
var range = connections._start + connections._count;
connectionsDiv.innerHTML = "<p>Displaying " + start + "-" + range + " of " + connections._total + " connections.</p>";
var members = connections.values; // The list of members you are connected to
for (var member in members) {
connectionsDiv.innerHTML += "<p>" + members[member].firstName + " " + members[member].lastName
+ " works in the " + members[member].industry + " industry"+ " ID: " + members[member].id ;
}
}
And if you want to see a list of new connections of your friend, I have one approach but haven't attempted yet. You can query LinkedIn database once/sec, and keep tracking of who is adding new connection. This is far beyond 100% accurate, but at least it gives you a list of connections.
Again, LinkedIn says you cannot store any information you obtained through API. That approach might be bad. If you query the server once/sec, probably your IP will be blocked as well.... so .... I conclude LinkedIn API is very limited.
I am using Firebase to develop an HTML5 mobile messaging app. I encountered an issue that I am unable to resolve. The app has multiple channels (chat rooms). When a message is added for the first time to a channel it works as expected but when I go to a different channel and post an new message to that channel then I return to the previous channel and post another message I get duplicates of the last posted message. When I reload the page the duplicates are gone but I'd prefer not to have duplicates showing at all. Below is my code:
function loadChatMessages(channelID) {
$('#chatMessages').html('');
var msgObj = {};
var channelRef = globals.channelsBase + '/' + channelID + '/messages';
var channelMessages = new Firebase(channelRef);
channelMessages.on('child_added', function (snapshot) {
msgObj = snapshot.val();
var id = snapshot.name().toString();
var messageTime = application.Functions.renderTime(msgObj.messageTime);
var tails = '<div class="message-tails-wrap"><div class="message-tails"></div></div>';
var html = '<li class="chatEl ' + sentByClass + '" id="'+id+'">';
html += tails;
html += msgObj.message;
html += '<span class="sender"> ' + by + ' </span> <span class="tmp-recipient"> ' + msgObj.recipient + ' </span>';
html += '<span class="time-stamp msg-time" >';
html += messageTime;
html += '</span></li>';
$(html).appendTo('#chatMessages');
/// TODO: TEMP solution!
var prevID = 0;
$('#chatMessages li').each(function(n) {
var id = $(this).attr('id');
if(id == prevID){
// console.log(id + ' is a duplicate. Remove it');
this.remove(); // the necessary evil....
}
prevID = id;
});
});
}
It sounds like you run loadChatMessages() every time you enter a room, and as your users move around rooms, you're seeing duplicate calls to your on('child_added' callback.
This is because you're adding a new callback every time you re-enter a room. To resolve this, do some clean up when your users leave a room. In that clean up function, make sure you remove the old listener using .off("child_added").
The event :
YOURREF.limitToLast(1).on('child_added', function (OBJECTADDED){
console.log(OBJECTADDED.key(), OBJECTADDED.val());
});
You may think the above code will e fired one time, this is not true. The above console.log will be fired twice, once with OBJECTADDED as the last object in the reference YOURREF before adding the new one, and another with the new one.