<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;CEUNQH06fCp7ImA9WhFSFUQ.&quot;"><id>tag:blogger.com,1999:blog-1377183911445147227</id><updated>2013-06-18T14:51:31.314-07:00</updated><category term="Apps Script" /><category term="Resellers" /><category term="Google Sites API" /><category term="Freemium" /><category term="analytics" /><category term="Gmail APIs" /><category term="Google Data Protocol" /><category term="SaaS" /><category term="Charts" /><category term="Community" /><category term="Staff Picks" /><category term="python" /><category term="Cloud Storage API" /><category term="Administrative APIs" /><category term="Guest Post" /><category term="oauth" /><category term="Android" /><category term="Google I/O" /><category term="Google Contacts API" /><category term="Google+" /><category term="Google Forms" /><category term="Mobile" /><category term="mpstaffpick" /><category term="java" /><category term="Google Prediction API" /><category term="Chrome OS" /><category term="webinar" /><category term="Migration" /><category term="Gadgets" /><category term="Auth" /><category term="Google Docs API" /><category term="OpenID" /><category term="Groups" /><category term="App Engine" /><category term="billing" /><category term="ISVs" /><category term="PHP" /><category term="Google Apps Directory API" /><category term="googlenew" /><category term="Developers" /><category term="AdSense" /><category term="Google Talk" /><category term="Ruby" /><category term="Google Calendar API" /><category term="Marketplace" /><category term="Google Profiles API" /><category term="Google Tasks API" /><category term="marketing" /><category term="Google Spreadsheets API" /><category term="Fusion Tables" /><category term="JavaScript" /><category term="Drive SDK" /><category term="Marketplace ISV Guest" /><category term=".NET" /><title>Google Apps Developer Blog</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://googleappsdeveloper.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://googleappsdeveloper.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>268</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/GoogleAppsDeveloperBlog" /><feedburner:info uri="googleappsdeveloperblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>GoogleAppsDeveloperBlog</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><entry gd:etag="W/&quot;A0MEQno4fip7ImA9WhFSFUU.&quot;"><id>tag:blogger.com,1999:blog-1377183911445147227.post-6259414979677305761</id><published>2013-06-18T14:03:00.000-07:00</published><updated>2013-06-18T14:03:23.436-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-06-18T14:03:23.436-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Developers" /><category scheme="http://www.blogger.com/atom/ns#" term="Drive SDK" /><title>Optimizing Drive API calls</title><content type="html">&lt;p&gt;Ever look at the data returned when using the Drive API? A &lt;code&gt;files.list&lt;/code&gt; call, even if just returning a single file, can yield upwards of 4kb of data. Drive has a rich set of metadata about files, but chances are your application only needs a small fraction of what’s available.&lt;/p&gt;

&lt;p&gt;One of the simplest but most effective optimizations you can make when building apps with the Drive API is limiting the amount of data returned to only those fields needed for your particular use case. The &lt;a href="https://developers.google.com/drive/performance#partial"&gt;fields query parameter&lt;/a&gt; gives you that control, and the results can be dramatic.&lt;/p&gt;

&lt;p&gt;A simple example of this is using the &lt;code&gt;files.list&lt;/code&gt; call to display a list of files to a user. The naive query, &lt;code&gt;https://www.googleapis.com/drive/v2/files?maxResults=100&lt;/code&gt;, generated more than 380kb of data when I ran it against my own corpus. But to render this list nicely, an app only needs a few bits of information -- the document title, icon &amp; thumbnail URLs, the mime type, and of course the file ID.&lt;/p&gt;

&lt;p&gt;Using the fields query parameter, the results can be trimmed to just the necessary fields and those needed for fetching subsequent pages of data. The optimized query is &lt;code&gt;https://www.googleapis.com/drive/v2/files?maxResults=100&amp;fields=items(iconLink%2Cid%2Ckind%2CmimeType%2CthumbnailLink%2Ctitle)%2CnextPageToken&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After modifying the query the resulting data was only 30k. That’s more than a 90% reduction in data size! Besides reducing the amount of data on the wire, these hints also enable us to further optimize how queries are processed. Not only is there less data to send, but also less time spent getting it in the first place.&lt;/p&gt;

&lt;p&gt;&lt;table cellpadding="5" cellspacing="0"&gt;&lt;tbody&gt;&lt;br /&gt;&lt;tr style="background-color: #f2f2f2;"&gt;&lt;td&gt;&lt;img class="profile" src="http://sites.google.com/site/developeradvocates/image/steve_bazyl.png" /&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;span class="largefont"&gt;Steven Bazyl&lt;/span&gt;  &amp;nbsp; &lt;a class="alt" href="https://plus.google.com/103354693083460731603/" rel="me" target="_blank"&gt;profile&lt;/a&gt; | &lt;a class="alt" href="http://twitter.com/stevenbazyl" rel="me" target="_blank"&gt;twitter&lt;/a&gt;&lt;br /&gt;&lt;div class="bio"&gt;&lt;br /&gt;Steve is a Developer Advocate for Google Drive and enjoys helping developers build better apps.&lt;/div&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GoogleAppsDeveloperBlog/~4/OJVykAI9W38" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://googleappsdeveloper.blogspot.com/feeds/6259414979677305761/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1377183911445147227&amp;postID=6259414979677305761&amp;isPopup=true" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/6259414979677305761?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/6259414979677305761?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GoogleAppsDeveloperBlog/~3/OJVykAI9W38/optimizing-drive-api-calls.html" title="Optimizing Drive API calls" /><author><name>Google Apps Developer Blog Editor</name><uri>http://www.blogger.com/profile/07808045840831274565</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://googleappsdeveloper.blogspot.com/2013/06/optimizing-drive-api-calls.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C04CQH09eip7ImA9WhFSFEQ.&quot;"><id>tag:blogger.com,1999:blog-1377183911445147227.post-1470527651405338688</id><published>2013-06-17T10:59:00.000-07:00</published><updated>2013-06-17T10:59:21.362-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-06-17T10:59:21.362-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Apps Script" /><category scheme="http://www.blogger.com/atom/ns#" term="Guest Post" /><title>Requesting Google Groups in a Domain through Apps Script</title><content type="html">&lt;p&gt;&lt;em&gt;Editor’s Note: Guest author Niels Buekers is a Google Apps consultant at &lt;a href="http://www.be.capgemini.com/"&gt;Capgemini Belgium&lt;/a&gt;. — Arun Nagarajan&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;During a recent Google Apps migration project, we received several requests to create custom groups of contacts so that users could more easily email frequent collaborators. Before switching to Google Apps, users created their own private distribution lists — but this approach led to overlapping groups that quickly fell out of sync.&lt;/p&gt;

&lt;p&gt;The problem was a perfect case for &lt;a href="https://developers.google.com/apps-script/"&gt;Google Apps Script&lt;/a&gt;. We built a great solution that gives users as much power as possible with just a quick administrator review.&lt;/p&gt;
&lt;br&gt;
&lt;a href="http://4.bp.blogspot.com/-agMMJfRRhEg/Ubul0crvdaI/AAAAAAAAAfU/Wzes57KppjE/s1600/domain-groups1.png" imageanchor="1" &gt;&lt;img border="0" src="http://4.bp.blogspot.com/-agMMJfRRhEg/Ubul0crvdaI/AAAAAAAAAfU/Wzes57KppjE/s520/domain-groups1.png" /&gt;&lt;/a&gt;

&lt;p&gt;&lt;em&gt;&lt;center&gt;The situation before: either manually adding each contact or using a private contacts group.&lt;/center&gt;&lt;/em&gt;&lt;/p&gt;
&lt;br&gt;
&lt;h3&gt;Solution overview&lt;/h3&gt;

&lt;p&gt;To start the process, a user adds a specific label to a Gmail message. A script that runs on a &lt;a href="https://developers.google.com/apps-script/execution_time_triggers"&gt;timed trigger&lt;/a&gt; then generates a request to create a group for all the addresses in the message. The script writes this data to a spreadsheet that tracks group names and administrator approval.&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
/**
 * Retrieves all 'group_request' threads and creates a request.
 */
function processInbox() {
  // Get threads that have the group_request label.
  var groupRequestLabel = GmailApp.getUserLabelByName('group_request');
  var threads = groupRequestLabel.getThreads(0, 10);
  
  // For each thread, retrieve all recipients and create a group request.
  for (var i = 0; i &lt; threads.length; i++) {
    var firstMessage = threads[i].getMessages()[0];
    var sender = firstMessage.getFrom();
    var recipients = [];
    
    // Add sender.
    recipients.push(parseAddresses(sender));
    
    // Add recipients.
    if (threads[i].getMessages()[0].getTo()) {
      var toRecipients = parseAddresses(firstMessage.getTo());
      recipients.push(toRecipients);
    }
    
    // Add CCs.
    if (threads[i].getMessages()[0].getCc()){
      var ccRecipients = parseAddresses(firstMessage.getCc());
      recipients.push(ccRecipients);
    }

    // Write all recipients to a cell in the spreadsheet
    // and send emails to ask for group name and approval.
    createGroupRequestForRecipients(recipients,
        Session.getActiveUser().getEmail());
    
    // Remove label from this thread now that it has been processed.
    threads[i].removeLabel(groupRequestLabel);
  }
};
&lt;/pre&gt;
&lt;br&gt;
&lt;h3&gt;Handling the request&lt;/h3&gt;

&lt;p&gt;Once the request has been processed and written to the spreadsheet, the script sends the user an email that asks her to suggest a name for the group in an Apps Script web app. A second email asks the administrator to visit the web app to approve or decline the request. The results are again stored in the spreadsheet.&lt;/p&gt;

&lt;p&gt;The spreadsheet contains a second script, which is triggered for each modification. Once the script confirms that the request has been approved, it uses the Apps Script &lt;a href="https://developers.google.com/apps-script/reference/domain/"&gt;Domain Service&lt;/a&gt; to create the new group.&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
/**
 * Creates a new group in the Google Apps cPanel with the provided name
 * and members.
 */
function createGroupWithAddresses(addresses,groupName){
  var group = GroupsManager.createGroup(groupName, groupName, groupName,
    GroupsManager.PermissionLevel.DOMAIN);
  var splitAddresses = addresses.split(',');
  for (var i = 0; i &lt; splitAddresses.length; i++) {
    Logger.log('Adding ' + splitAddresses[i]);
    group.addMember(splitAddresses[i]);
  }
};
&lt;/pre&gt;
&lt;br&gt;
&lt;a href="http://4.bp.blogspot.com/-1NRU8S7WfJU/Ubul0T0fI_I/AAAAAAAAAfc/kj6QkJM37t4/s1600/domain-groups2.png" imageanchor="1" &gt;&lt;img border="0" src="http://4.bp.blogspot.com/-1NRU8S7WfJU/Ubul0T0fI_I/AAAAAAAAAfc/kj6QkJM37t4/s520/domain-groups2.png" /&gt;&lt;/a&gt;

&lt;p&gt;&lt;em&gt;&lt;center&gt;The result after successfully running the script.&lt;/center&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This solution provides a simple way for users to request new Google groups, without all the overhead of manually creating an admin-managed distribution list.&lt;/p&gt;

&lt;table cellpadding="5" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr style="background-color: #f2f2f2;"&gt;&lt;td&gt;&lt;img class="profile" src="http://4.bp.blogspot.com/-h8gQn5-JNto/Ubul0G5348I/AAAAAAAAAfQ/cKlxKduzYx0/s1600/niels.png" /&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;span class="largefont"&gt;Niels Buekers&lt;/span&gt; &amp;nbsp;   &lt;a class="alt" href="http://plus.google.com/u/0/114064361311328965132/" rel="me" target="_blank"&gt;profile&lt;/a&gt; | &lt;a class="alt" href="http://twitter.com/Pega88" rel="me" target="_blank"&gt;Twitter&lt;/a&gt; &lt;br /&gt;&lt;div class="bio"&gt;&lt;br /&gt;Niels is a Google Apps consultant at &lt;a href="http://www.be.capgemini.com/"&gt;Capgemini Belgium&lt;/a&gt;, with interest in both the technical track and change management. He recently visited Google’s London office to participate in a Google Apps Script hackathon, which resulted in the above solution. Niels is a strong believer in cloud solutions and loves to spread the word about Google Apps.&lt;/div&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;img src="http://feeds.feedburner.com/~r/GoogleAppsDeveloperBlog/~4/W61Ewc1LfWM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://googleappsdeveloper.blogspot.com/feeds/1470527651405338688/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1377183911445147227&amp;postID=1470527651405338688&amp;isPopup=true" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/1470527651405338688?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/1470527651405338688?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GoogleAppsDeveloperBlog/~3/W61Ewc1LfWM/requesting-google-groups-in-domain.html" title="Requesting Google Groups in a Domain through Apps Script" /><author><name>Dan Lazin</name><uri>http://www.blogger.com/profile/09964717220244223276</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-agMMJfRRhEg/Ubul0crvdaI/AAAAAAAAAfU/Wzes57KppjE/s72-c/domain-groups1.png" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://googleappsdeveloper.blogspot.com/2013/06/requesting-google-groups-in-domain.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0UFRns5cCp7ImA9WhFSEk8.&quot;"><id>tag:blogger.com,1999:blog-1377183911445147227.post-5752799336906380290</id><published>2013-06-10T09:00:00.000-07:00</published><updated>2013-06-14T07:46:57.528-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-06-14T07:46:57.528-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Drive SDK" /><title>From a need to a startup, thanks to a Google hackathon</title><content type="html">&lt;div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;"&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;i style="background-color: white; font-family: Arial, Helvetica, sans-serif; font-size: 12px; line-height: 15.59375px; white-space: normal;"&gt;Editor’s Note: Guest author Arnaud Breton is a co-founder of &lt;a href="http://unishared.com/"&gt;UniShared&lt;/a&gt;&amp;nbsp;— Nicolas Garnier&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;A few weeks ago, &lt;/span&gt;&lt;a href="https://plus.google.com/115727873029132210083/posts" style="text-decoration: none;"&gt;&lt;span style="background-color: transparent; color: #1155cc; font-family: Arial; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;Clément&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt; and &lt;/span&gt;&lt;a href="https://plus.google.com/106654088105839575001/posts" style="text-decoration: none;"&gt;&lt;span style="background-color: transparent; color: #1155cc; font-family: Arial; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;I&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt; started to take online courses (based on videos), mainly on &lt;/span&gt;&lt;a href="http://coursera.org/" style="text-decoration: none;"&gt;&lt;span style="background-color: transparent; color: #1155cc; font-family: Arial; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;Coursera&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;, &lt;/span&gt;&lt;a href="http://edxonline.org/" style="text-decoration: none;"&gt;&lt;span style="background-color: transparent; color: #1155cc; font-family: Arial; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;edX&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt; (the MIT-Harvard venture), and &lt;/span&gt;&lt;a href="https://www.udacity.com/" style="text-decoration: none;"&gt;&lt;span style="background-color: transparent; color: #1155cc; font-family: Arial; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;Udacity&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;, the biggest online course providers.&lt;/span&gt;&lt;/div&gt;
&lt;b id="docs-internal-guid-080c971b-2e64-d306-a582-68beae3e4d9e" style="font-weight: normal;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/b&gt;

&lt;br /&gt;
&lt;div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;"&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Right from the start, we found that it was really painful to take digital notes while watching the video lectures: we had to switch between multiple windows, struggling to interact with them (no shortcuts to play/pause, etc) and no ways of matching the notes to videos... Finally we ended up taking notes with the old fashioned and archaic pens &amp;amp; papers.&lt;/span&gt;&lt;/div&gt;
&lt;b style="font-weight: normal;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/b&gt;

&lt;br /&gt;
&lt;div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;"&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;After giving it a thought, we were convinced that we could make this much better. We both live in Mountain View, fifteen minutes away from the Google HQ, where a &lt;/span&gt;&lt;a href="http://googleappsdeveloper.blogspot.ch/2013/03/google-drive-hackathon-in-mountain-view.html" style="text-decoration: none;"&gt;&lt;span style="background-color: transparent; color: #1155cc; font-family: Arial; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;Google Drive hackathon&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt; was taking place so we decided to take this opportunity to find and build a solution to our problem. And we came up with the idea of a simple Google Drive app, which would embed both the video lectures and the notes, in the same window, letting us leverage all the shortcuts. Additionally, it would enable us to synchronize the notes with the videos, to be able to smoothly go to the related part of the videos while studying our notes. During the two days - and two nights - we developed that missing app, helped by the amazing Googlers from the Drive team and meeting other amazing people who came to also give birth to their ideas or to help us.&lt;/span&gt;&lt;/div&gt;
&lt;b style="font-weight: normal;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/b&gt;

&lt;br /&gt;
&lt;div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;"&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;As a tech guy, it was a new exciting challenge to build this app, especially in such a short time. Fortunately, leveraging Google robust and powerful infrastructure and frameworks made it possible. It seemed obvious for us to leverage the Google Drive and Youtube APIs, to host our app on Google App Engine and to build it with the amazing &lt;/span&gt;&lt;a href="http://angularjs.org/" style="text-decoration: none;"&gt;&lt;span style="background-color: transparent; color: #1155cc; font-family: Arial; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;AngularJS&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;.&lt;/span&gt;&lt;/div&gt;
&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;

&lt;br /&gt;
&lt;div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;"&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;At the end of the hackathon, we managed to get a viable app, enabling students to create, save and synchronize their notes and videos. We were even rewarded by the Drive team who gave us a prize for our efforts!&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;span id="docs-internal-guid-080c971b-2e65-19c7-4f18-06660661a5a5"&gt;&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;a href="http://videonot.es/" style="text-decoration: none;"&gt;&lt;span style="color: #1155cc; font-family: Arial; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;VideoNot.es&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt; was born!&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style="text-align: center;"&gt;
&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;img src="https://lh4.googleusercontent.com/YFXtZGu9rUfMfwRBGlhLehOFdAT4AY8HaOaJuMC6whOJg8TjJe9M6EuUwzKCIYf_-4VmneAii2yA3Zjad9kn_zQLS1hXanXcM8rlbSeh8JxrsN26813whdFN" style="border-width: 0; padding: 0;" width="550" /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;span id="docs-internal-guid-080c971b-2e65-b1d6-53a7-14953dcbb8cf"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;"&gt;
&lt;span id="docs-internal-guid-080c971b-2e65-b1d6-53a7-14953dcbb8cf"&gt;&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;A few hours later, we started to spread the word about our new app and were convinced that it could be as useful for other students as it was for us. Immediately, hundreds of students started to use it, giving us useful feedback on what mattered the most to them. Based on their feedback, we continued to improve our app, with the number of users increasing. Today, one month after the hackathon, more than 300 VideoNotes are created daily all around the world, and the number continues to grow day after day!&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;span id="docs-internal-guid-080c971b-2e65-b1d6-53a7-14953dcbb8cf"&gt;&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;"&gt;
&lt;span id="docs-internal-guid-080c971b-2e65-b1d6-53a7-14953dcbb8cf"&gt;&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;We also got featured on The Next Web describing VideoNot.es as &lt;/span&gt;&lt;span style="color: #1155cc; font-family: Arial; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;a href="http://thenextweb.com/apps/2013/04/16/videonotes-a-really-simple-way-to-make-store-and-share-notes-about-online-videos-as-you-watch-them/?fromcat=all" style="text-decoration: none;"&gt;“a really useful tool to make, store and share notes about online videos as you watch them”&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;span id="docs-internal-guid-080c971b-2e65-b1d6-53a7-14953dcbb8cf"&gt;
&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;"&gt;
&lt;span id="docs-internal-guid-080c971b-2e65-b1d6-53a7-14953dcbb8cf"&gt;&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;So, what’s next for us?&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Arial; line-height: 1.15; white-space: pre-wrap;"&gt;Obviously, continuing to improve the app based on feedback is our top priority.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Arial; line-height: 1.15; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;"&gt;
&lt;span id="docs-internal-guid-080c971b-2e65-b1d6-53a7-14953dcbb8cf"&gt;&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;Also, we have discovered new use-cases where VideoNot.es can be useful. For example journalists contacted us to tell us that they use it to write articles based on interview records. But also people in charge of the transcription of videos are also very excited about VideoNot.es.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;span id="docs-internal-guid-080c971b-2e65-b1d6-53a7-14953dcbb8cf"&gt;
&lt;br /&gt;&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;"&gt;
&lt;span id="docs-internal-guid-080c971b-2e65-b1d6-53a7-14953dcbb8cf"&gt;&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;It got us more convinced than ever that note-taking can be drastically improved, especially by adapting it to its learning context. We want to go even further. Bringing back social interactions in online classrooms, letting students easily share their notes, again leveraging Google Drive was the first step. Adding real-time collaboration and Q&amp;amp;A features is the second step and we will definitely take advantage of the &lt;/span&gt;&lt;a href="http://developers.google.com/drive/realtime" style="text-decoration: none;"&gt;&lt;span style="color: #1155cc; font-family: Arial; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;Google Drive Realtime API&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt; for this.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;span id="docs-internal-guid-080c971b-2e65-b1d6-53a7-14953dcbb8cf"&gt;
&lt;br /&gt;&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;Thanks a lot to the Drive team who organized this hackathon to give our idea a try through their amazing tools! And this is just the beginning of the adventure, that started from a problem we faced, whose solution has been found at the Google hackathon, and which is just starting to reach its potential.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;table cellpadding="5" cellspacing="0" style="background-color: white; color: black; font-family: Arial, Helvetica, sans-serif; font-size: 12px; line-height: 15.59375px;"&gt;&lt;tbody&gt;
&lt;tr style="background-color: #f2f2f2;"&gt;&lt;td&gt;&lt;span id="docs-internal-guid-080c971b-2e71-2193-fc3c-62f23036f52e"&gt;

&lt;img class="profile" src="https://lh3.googleusercontent.com/tpT0De6YKA0F4S1LYPFM6SxLn8FMUQNV8rJN6l9lMyVK8om1dSFBikmitgJCasy6VU8v0rkgyfIUurJQa1ZtEdGJ2tPPxS8MMXkJcCTSX_M4EYtiIY6vbmwE" style="border: 1px solid rgb(204, 204, 204); height: auto; margin-top: 4px; padding: 1px; width: 64px;" /&gt;&lt;/span&gt;
&lt;/td&gt;&lt;td valign="top"&gt;&lt;span class="largefont" style="font-size: medium; font-weight: bold;"&gt;Arnaud Breton&lt;/span&gt;&amp;nbsp;&lt;a class="alt" href="https://plus.google.com/106654088105839575001/" rel="me" style="color: #5588bb; text-decoration: none;" target="_blank"&gt;profile&lt;/a&gt;
&lt;br /&gt;
&lt;div class="bio"&gt;
&lt;br /&gt;
&lt;span id="docs-internal-guid-080c971b-2e70-b907-beea-7a0b2df90676"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="background-color: transparent; font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;Arnaud Breton is passionate about the impact that technologies have on the world. &amp;nbsp;He is the co-founder and CTO of &lt;/span&gt;&lt;a href="http://unishared.com/" style="text-decoration: none;"&gt;&lt;span style="background-color: transparent; color: #1155cc; font-family: Arial; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;UniShared&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt; / &lt;/span&gt;&lt;a href="http://videonot.es/" style="text-decoration: none;"&gt;&lt;span style="background-color: transparent; color: #1155cc; font-family: Arial; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;VideoNot.es&lt;/span&gt;&lt;/a&gt;&lt;span style="background-color: transparent; font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;div class="post-share-buttons" style="background-color: white; display: inline-block; font-family: Arial, Helvetica, sans-serif; font-size: 12px; line-height: 15.59375px; margin-top: 0.5em; vertical-align: middle; white-space: normal;"&gt;
&lt;/div&gt;
&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;
&lt;/span&gt;&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/GoogleAppsDeveloperBlog/~4/OwUonbyJ8Ls" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://googleappsdeveloper.blogspot.com/feeds/5752799336906380290/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1377183911445147227&amp;postID=5752799336906380290&amp;isPopup=true" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/5752799336906380290?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/5752799336906380290?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GoogleAppsDeveloperBlog/~3/OwUonbyJ8Ls/from-need-to-startup-thanks-to-google.html" title="From a need to a startup, thanks to a Google hackathon" /><author><name>Nicolas</name><uri>http://www.blogger.com/profile/03719691547528812848</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://googleappsdeveloper.blogspot.com/2013/06/from-need-to-startup-thanks-to-google.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEEBRnkzeCp7ImA9WhFTFk4.&quot;"><id>tag:blogger.com,1999:blog-1377183911445147227.post-5836773259515482043</id><published>2013-06-07T12:17:00.000-07:00</published><updated>2013-06-07T12:17:37.780-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-06-07T12:17:37.780-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Apps Script" /><category scheme="http://www.blogger.com/atom/ns#" term="Guest Post" /><title>For shipping jewelry, Apps Script is golden</title><content type="html">&lt;p&gt;&lt;i&gt;Editor’s Note: Guest author Jason Gordon is a co-founder of &lt;a href="http://www.bethmacri.com/"&gt;Beth Macri Designs&lt;/a&gt; — Arun Nagarajan&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.bethmacri.com/"&gt;Beth Macri Designs&lt;/a&gt; creates jewelry from the point of view of a structural engineer. The forms are designed using generative 3D software systems and materialized using 3D printing technologies. Our company understands that to make beautiful fine jewelry, 3D printing is only the first step; traditional jewelry craft is then employed for final production. After our first product, The Hidden Message Necklace, was recently &lt;a href="http://www.youtube.com/watch?v=bEnMvAtV8tw"&gt;featured on The View&lt;/a&gt; as part of its Valentine's Day Gift Guide, we had a lot of orders to ship out. As soon as the mail leaves the building, though, the process is literally out of our hands: something unexpected was bound to happen to at least one or two packages. Several package-tracking services exist, but getting the names and tracking numbers into them was a cut-and-paste operation.&lt;/p&gt;

&lt;p&gt;I knew that all of the tracking numbers were being delivered by email and I had already set up a Gmail filter to archive them and apply a label. With a little help from Google Apps Script, I knew I could automatically parse those emails and add them to my account on &lt;a href="http://www.packagetrackr.com/"&gt;PackageTrackr&lt;/a&gt; (which syncs to their newer service, &lt;a href="http://www.faranow.com/"&gt;Fara&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jasongordon/google-apps-script"&gt;The script&lt;/a&gt; supports reading emails from multiple shipping providers and is set up so one could easily add more. Every 30 minutes on a &lt;a href="https://developers.google.com/apps-script/execution_time_triggers"&gt;time-driven trigger&lt;/a&gt;, using the &lt;a href="https://developers.google.com/apps-script/reference/gmail/"&gt;Gmail service&lt;/a&gt;, the script runs and looks through unread emails from the shipping provider label, then parses the name and tracking number out of each one. The provider, tracking number, and recipient are stored in a JavaScript array.&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
function getUSPSConversations(){
  return GmailApp.search("in:usps is:unread subject:(Click-N-Ship)");
}

function matchUSPSHTML(data){
  var out = [];
  var track_num = data.match( 
      /TrackConfirmAction\Winput\.action\WtLabels\=(\d+)/g);
  var to = data.match(/Shipped.to.*[\r\n]*.*&gt;([a-zA-Z\s-_]*)&amp;lt;br&amp;gt;/g);
  for(i in track_num){
    var o = new Object();
    var track = track_num[i].match(/(\d+)/g);
    var person = to[i].match(/&gt;([a-zA-Z\s-_]+)&amp;lt;br&amp;gt;/);
    var myPerson = person[1].replace(/(\r\n|\n|\r)/gm,"")
    o["number"]=track[0];
    o["carrier"]="USPS";
    o["person"]=myPerson;
    out.push(o);
  }
  return out;
}
&lt;/pre&gt;

&lt;p&gt;You can parse all of your different shipping providers in one run of the script. After the all of the shipment emails are read, it composes an email to PackageTrackr to give it all of the tracking numbers it just harvested.&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
var user = Session.getActiveUser().getEmail();
if(data.length &gt; 0){    
  for(d in data){
    body += this["formatForPackageTrackr"](data[d]["number"], 
        data[d]["carrier"], data[d]["person"]);
  }
  
  GmailApp.sendEmail("track@packagetrackr.com", "Add Packages",
      body, {bcc: user});
}

function formatForPackageTrackr(tracking_num, service, person){
  return "#:" + tracking_num + " " + service + " " + person + "\n";
}
&lt;/pre&gt;

&lt;p&gt;Down the line, other shipping providers could be added such as UPS and Fedex.  Additionally, more tracking services could be added instead of just PackageTrackr.&lt;/p&gt;

&lt;table cellpadding="5" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr style="background-color: #f2f2f2;"&gt;&lt;td&gt;&lt;img class="profile" src="http://3.bp.blogspot.com/-uJ4rNr0xLxQ/Ua-mQIPZBmI/AAAAAAAAAd8/FGoOQFBjvOE/s320/jason.png" /&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;span class="largefont"&gt;Jason Gordon&lt;/span&gt; &amp;nbsp;   &lt;a class="alt" href="https://plus.google.com/116136064088278075340/posts" rel="me" target="_blank"&gt;profile&lt;/a&gt;&lt;br /&gt;&lt;div class="bio"&gt;&lt;br /&gt;Jason Gordon is a co-founder at jewelry startup &lt;a href="http://www.bethmacri.com/"&gt;Beth Macri Designs&lt;/a&gt;. He is responsible for software development, logistics and e-commerce.  While working at Beth Macri Designs, Jason gets to find creative ways to put his software development skills to work to improve logistics and user experience. 
&lt;/div&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;img src="http://feeds.feedburner.com/~r/GoogleAppsDeveloperBlog/~4/g9JL32cMcMs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://googleappsdeveloper.blogspot.com/feeds/5836773259515482043/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1377183911445147227&amp;postID=5836773259515482043&amp;isPopup=true" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/5836773259515482043?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/5836773259515482043?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GoogleAppsDeveloperBlog/~3/g9JL32cMcMs/for-shipping-jewelry-apps-script-is.html" title="For shipping jewelry, Apps Script is golden" /><author><name>Dan Lazin</name><uri>http://www.blogger.com/profile/09964717220244223276</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-uJ4rNr0xLxQ/Ua-mQIPZBmI/AAAAAAAAAd8/FGoOQFBjvOE/s72-c/jason.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://googleappsdeveloper.blogspot.com/2013/06/for-shipping-jewelry-apps-script-is.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0UAQ30yfip7ImA9WhFSEk8.&quot;"><id>tag:blogger.com,1999:blog-1377183911445147227.post-8819472636400651729</id><published>2013-05-28T09:00:00.000-07:00</published><updated>2013-06-14T07:47:22.396-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-06-14T07:47:22.396-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Drive SDK" /><title>What does storage quota unification mean for the Drive API?</title><content type="html">&lt;b id="docs-internal-guid-4c91acfe-ea4e-8778-abf7-b6fe906c8490" style="font-weight: normal;"&gt;&lt;/b&gt;&lt;br /&gt;
&lt;div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;"&gt;
&lt;b id="docs-internal-guid-4c91acfe-ea4e-8778-abf7-b6fe906c8490" style="font-weight: normal;"&gt;&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;Earlier this month, &lt;/span&gt;&lt;a href="http://googledrive.blogspot.com/2013/05/bringing-it-all-together-15-gb-now.html" style="text-decoration: none;"&gt;&lt;span style="color: #1155cc; font-family: Arial; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;we announced&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt; that storage quota is now shared between Google Drive, GMail, and Google+ photos. As part of this change, the &lt;/span&gt;&lt;a href="https://developers.google.com/drive/" style="text-decoration: none;"&gt;&lt;span style="color: #1155cc; font-family: Arial; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;Google Drive API&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt; and the &lt;/span&gt;&lt;a href="https://developers.google.com/google-apps/documents-list/" style="text-decoration: none;"&gt;&lt;span style="color: #1155cc; font-family: Arial; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"&gt;Google Documents List API&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt; will be updated over the next few weeks to start returning the updated storage quota information.&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;b id="docs-internal-guid-4c91acfe-ea4e-8778-abf7-b6fe906c8490" style="font-weight: normal;"&gt;&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/b&gt;

&lt;br /&gt;
&lt;div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;"&gt;
&lt;b id="docs-internal-guid-4c91acfe-ea4e-8778-abf7-b6fe906c8490" style="font-weight: normal;"&gt;&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;In the Google Drive API, this appears in the &lt;/span&gt;&lt;span style="font-family: Courier New, Courier, monospace; vertical-align: baseline; white-space: pre-wrap;"&gt;about&lt;/span&gt;&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt; collection.&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;b id="docs-internal-guid-4c91acfe-ea4e-8778-abf7-b6fe906c8490" style="font-weight: normal;"&gt;&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/b&gt;

&lt;br /&gt;
&lt;div style="background-color: #f8f8f8; border-radius: 5px; border: 1px solid #bbb; color: #444444; padding: 15px;"&gt;
&lt;div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;"&gt;
&lt;b id="docs-internal-guid-4c91acfe-ea4e-8778-abf7-b6fe906c8490" style="font-weight: normal;"&gt;&lt;span style="font-weight: bold; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;span style="font-family: Courier New, Courier, monospace;"&gt;GET https://www.googleapis.com/drive/v2/about&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;b id="docs-internal-guid-4c91acfe-ea4e-8778-abf7-b6fe906c8490" style="font-weight: normal;"&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;br /&gt;&lt;span style="vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;
&lt;br /&gt;
&lt;div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;"&gt;
&lt;b id="docs-internal-guid-4c91acfe-ea4e-8778-abf7-b6fe906c8490" style="font-weight: normal;"&gt;&lt;span style="font-weight: bold; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;span style="font-family: Courier New, Courier, monospace;"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;b id="docs-internal-guid-4c91acfe-ea4e-8778-abf7-b6fe906c8490" style="font-weight: normal;"&gt;
&lt;/b&gt;
&lt;div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;"&gt;
&lt;b id="docs-internal-guid-4c91acfe-ea4e-8778-abf7-b6fe906c8490" style="font-weight: normal;"&gt;&lt;span style="font-weight: bold; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;span style="font-family: Courier New, Courier, monospace;"&gt; &amp;nbsp;"kind": "drive#about",&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;b id="docs-internal-guid-4c91acfe-ea4e-8778-abf7-b6fe906c8490" style="font-weight: normal;"&gt;


&lt;div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;"&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;span style="font-weight: bold; vertical-align: baseline; white-space: pre-wrap;"&gt; &amp;nbsp;&lt;/span&gt;&lt;span style="color: #980000; font-weight: bold; vertical-align: baseline; white-space: pre-wrap;"&gt;"quotaBytesTotal": 16106127360,&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;"&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;span style="font-weight: bold; vertical-align: baseline; white-space: pre-wrap;"&gt; &amp;nbsp;&lt;/span&gt;&lt;span style="color: #980000; font-weight: bold; vertical-align: baseline; white-space: pre-wrap;"&gt;"quotaBytesUsed": 17936436,&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;"&gt;
&lt;span style="font-weight: bold; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;span style="font-family: Courier New, Courier, monospace;"&gt; &amp;nbsp;…&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;"&gt;
&lt;span style="font-weight: bold; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;span style="font-family: Courier New, Courier, monospace;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/b&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;

&lt;br /&gt;
&lt;div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;"&gt;
&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;In the Documents List API, this appears in the &lt;/span&gt;&lt;span style="font-family: Courier New, Courier, monospace; vertical-align: baseline; white-space: pre-wrap;"&gt;metadata&lt;/span&gt;&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt; feed.&lt;/span&gt;&lt;/div&gt;
&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;


&lt;br /&gt;
&lt;div style="background-color: #f8f8f8; border-radius: 5px; border: 1px solid #bbb; color: #444444; padding: 15px;"&gt;
&lt;div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;"&gt;
&lt;span style="font-weight: bold; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;span style="font-family: Courier New, Courier, monospace;"&gt;GET https://docs.google.com/feeds/metadata/default&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;br /&gt;&lt;span style="font-weight: bold; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;"&gt;
&lt;span style="font-weight: bold; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;lt;entry&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;"&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;span style="font-weight: bold; vertical-align: baseline; white-space: pre-wrap;"&gt; &amp;nbsp;&lt;/span&gt;&lt;span style="color: #980000; font-weight: bold; vertical-align: baseline; white-space: pre-wrap;"&gt;&amp;lt;gd:quotaBytesTotal&amp;gt;16106127360&amp;lt;/gd:quotaBytesTotal&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;"&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;span style="font-weight: bold; vertical-align: baseline; white-space: pre-wrap;"&gt; &amp;nbsp;&lt;/span&gt;&lt;span style="color: #980000; font-weight: bold; vertical-align: baseline; white-space: pre-wrap;"&gt;&amp;lt;gd:quotaBytesUsed&amp;gt;17936436&amp;lt;/gd:quotaBytesUsed&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;"&gt;
&lt;span style="font-weight: bold; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;span style="font-family: Courier New, Courier, monospace;"&gt; &amp;nbsp;…&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;"&gt;
&lt;span style="font-weight: bold; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;lt;/entry&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;

&lt;div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;"&gt;
&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;The new values in the &lt;/span&gt;&lt;span style="font-family: Courier New, Courier, monospace; vertical-align: baseline; white-space: pre-wrap;"&gt;quotaBytesTotal&lt;/span&gt;&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt; field reflect total storage quota across all the unified products. If you rely on this value, you may notice a change in your apps, but we expect it to behave as if a user has just purchased more storage.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt;The new values for &lt;/span&gt;&lt;span style="font-family: Courier New, Courier, monospace; vertical-align: baseline; white-space: pre-wrap;"&gt;quotaBytesUsed&lt;/span&gt;&lt;span style="font-family: Arial; vertical-align: baseline; white-space: pre-wrap;"&gt; field will reflect the total amount of storage used across the unified products. &amp;nbsp;(This field used to reflect the total amount of storage used by Google Drive.)&lt;/span&gt;&lt;br /&gt;
&lt;b style="font-weight: normal;"&gt;&lt;span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;
&lt;b style="font-weight: normal;"&gt;&lt;span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;
&lt;br /&gt;
&lt;table cellpadding="5" cellspacing="0" style="background-color: white; color: black; font-family: Arial, Helvetica, sans-serif; font-size: 12px; line-height: 15.59375px;"&gt;&lt;tbody&gt;
&lt;tr style="background-color: #f2f2f2;"&gt;&lt;td&gt;&lt;img class="profile" src="https://sites.google.com/site/developeradvocates/image/ali_afshar.png" style="border: 1px solid rgb(204, 204, 204); height: 90px; margin-top: 4px; padding: 1px; width: 64px;" /&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;span class="largefont" style="font-size: medium; font-weight: bold;"&gt;Ali Afshar&lt;/span&gt;&amp;nbsp;&lt;a class="alt" href="https://plus.google.com/118327176775959145936/" rel="me" style="color: #5588bb; text-decoration: none;" target="_blank"&gt;profile&lt;/a&gt;&amp;nbsp;|&amp;nbsp;&lt;a class="alt" href="http://twitter.com/#!/aliafshar" style="color: #5588bb; text-decoration: none;"&gt;twitter&lt;/a&gt;&lt;br /&gt;
&lt;div class="bio"&gt;
&lt;br /&gt;
Tech Lead, Google Drive Developer Relations. As an eternal open source advocate, he contributes to a number of open source applications, and is the author of the PIDA Python IDE. Once an intensive care physician, he has a special interest in all aspects of technology for healthcare&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;img src="http://feeds.feedburner.com/~r/GoogleAppsDeveloperBlog/~4/2qotICof9L8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://googleappsdeveloper.blogspot.com/feeds/8819472636400651729/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1377183911445147227&amp;postID=8819472636400651729&amp;isPopup=true" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/8819472636400651729?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/8819472636400651729?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GoogleAppsDeveloperBlog/~3/2qotICof9L8/what-does-storage-quota-unification.html" title="What does storage quota unification mean for the Drive API?" /><author><name>Nicolas</name><uri>http://www.blogger.com/profile/03719691547528812848</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://googleappsdeveloper.blogspot.com/2013/05/what-does-storage-quota-unification.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU8FSX8_cSp7ImA9WhBbGE0.&quot;"><id>tag:blogger.com,1999:blog-1377183911445147227.post-7498506397450527128</id><published>2013-05-16T14:34:00.002-07:00</published><updated>2013-05-17T09:23:38.149-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-05-17T09:23:38.149-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Google+" /><category scheme="http://www.blogger.com/atom/ns#" term="Google Apps Directory API" /><category scheme="http://www.blogger.com/atom/ns#" term="Administrative APIs" /><title>Admin SDK and Google+ APIs for business</title><content type="html">Every day, millions of businesses, schools and government agencies rely on Google Apps to get their work done. And each of these organizations has an administrator (or a team of admins) responsible for tasks like creating new accounts, managing mobile devices, and specifying exactly which products and features their employees can use.&lt;br /&gt;
&lt;br /&gt;
Today, we're announcing the Admin SDK, which enables developers to build customized administrative tools for organizations that use Google Apps. The new Admin SDK consolidates many of the existing domain APIs into a new uniform structure and introduces new functionality with the Directory API and Reports API. We’re starting to pilot Google+ Domains API.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Directory API&lt;/h3&gt;
The new Directory API provides a simple, RESTful interface to support all basic operations required to query &amp;amp; manage users, groups, organizational units, Chromebooks and mobile devices.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Reports API&lt;/h3&gt;
The new Reports API gives developers a consolidated view of reporting and auditing for domains. Developers can build applications that can monitor and search across usage statistics and activities within a domain.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Google+ Domains API&lt;/h3&gt;
Businesses are using Google+ to help employees collaborate more easily and get things done. Developers will soon be able to auto-provision Circles, read/write posts, and more from the new APIs. &lt;a href="http://goo.gl/CitdT"&gt;Let us know&lt;/a&gt; if you're interested in learning more about this API when it's available.&lt;br /&gt;
&lt;br /&gt;
To begin using the Admin SDK follow the instructions in the &lt;a href="http://developers.google.com/admin-sdk"&gt;API documentation&lt;/a&gt;. You will need to sign in to the &lt;a href="https://code.google.com/apis/console"&gt;Google APIs Console&lt;/a&gt; and activate the Admin SDK. If you have any questions, join the conversation at &lt;a href="http://stackoverflow.com/questions/tagged/google-admin-sdk"&gt;Stack Overflow&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;Note about API deprecation:&lt;/i&gt;
&lt;br /&gt;
With the introduction of the Directory and Reporting APIs in the new Admin SDK the following APIs will be deprecated per their standard deprecation policy: Google Apps Profiles, Provisioning, Admin Audit, Reporting, Reporting Visualization.&lt;br /&gt;
&lt;br /&gt;
&lt;table cellpadding="5" cellspacing="0"&gt;&lt;tbody&gt;
&lt;tr style="background-color: #f2f2f2;"&gt;&lt;td&gt;&lt;img class="profile" src="https://lh4.googleusercontent.com/-unS5rFBjhYA/ThYSt0pFxFI/AAAAAAAAQZw/tiChwdjdRxc/w667-h665-no/IMG_5532.JPG" style="width: 94px;" width="94px" /&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;span class="largefont"&gt;Ajay Guwalani&lt;/span&gt; &amp;nbsp; 
&lt;br /&gt;
&lt;div class="bio"&gt;
&lt;br /&gt;
Ajay Guwalani is Product Manager on Google Apps Admin APIs. His current focus is to build next generation admin APIs to make enterprise developers and admins happy.&lt;/div&gt;
&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;img src="http://feeds.feedburner.com/~r/GoogleAppsDeveloperBlog/~4/qXbsJERttms" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://googleappsdeveloper.blogspot.com/feeds/7498506397450527128/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1377183911445147227&amp;postID=7498506397450527128&amp;isPopup=true" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/7498506397450527128?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/7498506397450527128?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GoogleAppsDeveloperBlog/~3/qXbsJERttms/admin-sdk-and-google-apis-for-business.html" title="Admin SDK and Google+ APIs for business" /><author><name>Google Apps Developer Blog Editor</name><uri>http://www.blogger.com/profile/07808045840831274565</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>5</thr:total><feedburner:origLink>http://googleappsdeveloper.blogspot.com/2013/05/admin-sdk-and-google-apis-for-business.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUECQ34_eyp7ImA9WhBaEEU.&quot;"><id>tag:blogger.com,1999:blog-1377183911445147227.post-1437599555417407224</id><published>2013-05-15T14:32:00.000-07:00</published><updated>2013-05-20T14:01:02.043-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-05-20T14:01:02.043-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Gmail APIs" /><title>Introducing Actions in the Inbox, powered by schemas</title><content type="html">&lt;p&gt;Search engines have been using structured data for years to understand the information on web pages and provide richer search results. Today, we are introducing schemas in emails to make messages more interactive and allow developers to deliver a slice of their apps to users’ inboxes.&lt;/p&gt;

&lt;p&gt;Schemas in emails can be used to represent various types of entities and actions. Email clients that understand schemas, such as Gmail, can render entities and actions defined in the messages with a consistent user interface.  In the case of Gmail, this means that the emails can display quick action buttons that let users take actions directly from their inboxes, as in the following screenshot:&lt;/p&gt;

&lt;div style="text-align:center;"&gt;
&lt;img border="0" style="border:none;" src="http://4.bp.blogspot.com/-l2vAzLwR7Ck/UZJ6FM69biI/AAAAAAAABCY/fydhxNXQnvg/s480/image00.png" /&gt;
&lt;/div&gt;

&lt;p&gt;Using schemas to add quick action buttons to the emails you send is easy. All it takes is adding some markup to your HTML emails, together with your regular content, in one of the supported formats - &lt;a href="https://developers.google.com/gmail/schemas/reference/formats/microdata"&gt;Microdata&lt;/a&gt; and &lt;a href="https://developers.google.com/gmail/schemas/reference/formats/json-ld"&gt;JSON-LD&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;As an example, the following JSON-LD markup can be used to define a movie and the corresponding one-click action to add the movie to your queue:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
&amp;lt;script type="application/ld+json"&amp;gt;
{
  "@context": "schema.org",
  "@type": "Movie",
  "name": "The Internship",
  ... information about the movie ...
  "action": {
    "@type": "ConfirmAction",
    "name": "Add to queue",
    "actionHandler": {
      "@type": "HttpActionHandler",
      "url": "https://my-movies.com/add?movieId=123",
      "method": "POST",
    }
  }
}
&amp;lt;/script&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Gmail renders the markup above with a button labelled “Add to queue” next to the email subject line. When the user clicks on the button, Gmail sends a POST request to the url specified in the action handler. Your app has to handle these requests and respond to the email client with an appropriate HTTP response code (200 for successful requests, 400 for invalid requests, etc.).&lt;/p&gt;

&lt;p&gt;Schemas in emails currently support four different types of actions - rate/review, RSVP, one-click action and goto link - and we plan to add more types moving forward. We are collaborating with a number of partners who will launch their integrations in the coming weeks, making the messages they send more useful and interactive for Gmail users. For example, &lt;a href="http://www.esna.com/"&gt;Esna&lt;/a&gt; is using this to inform users of missed calls and provide them with a one-click button to be called again, while &lt;a href="http://www.seamless.com"&gt;Seamless&lt;/a&gt; is implementing the rate/review action to collect feedback about restaurants.&lt;/p&gt;

&lt;p&gt;Other partners who are already implementing schemas in email today include both &lt;a href="https://www.billguard.com/"&gt;Billguard&lt;/a&gt;, &lt;a href="https://www.concur.com/"&gt;Concur Technologies&lt;/a&gt;, &lt;a href="http://www.docusign.com/"&gt;Docusign&lt;/a&gt;, &lt;a href="https://www.hellosign.com/"&gt;HelloSign&lt;/a&gt;, &lt;a href="http://www.insightly.com/"&gt;Insight.ly&lt;/a&gt;, &lt;a href="http://www.mailchimp.com"&gt;Mailchimp&lt;/a&gt;, &lt;a href="http://www.myerp.com"&gt;myERP&lt;/a&gt;, &lt;a href="http://www.netflix.com"&gt;Netflix&lt;/a&gt;, &lt;a href="http://www.opentable.com"&gt;OpenTable&lt;/a&gt;, &lt;a href="http://www.kissflow.com/"&gt;Orangescape&lt;/a&gt;, &lt;a href="http://www.paperlesspost.com/"&gt;Paperless Post&lt;/a&gt;, &lt;a href="https://www.spotify.com"&gt;Spotify&lt;/a&gt;, &lt;a href="http://www.sugarcrm.com/"&gt;SugarCRM&lt;/a&gt;, and &lt;a href="https://www.tripit.com/"&gt;Tripit&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To learn more about all supported entities and actions and to find out how to get started with schemas in email, visit &lt;a href="http://developers.google.com/gmail"&gt;http://developers.google.com/gmail&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;&lt;table cellpadding="5" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr style="background-color: #f2f2f2;"&gt;&lt;td&gt;&lt;img class="profile" src="http://4.bp.blogspot.com/-dlrMe7xZ-to/TlaWF9TImaI/AAAAAAAAAM4/ih9HtRk8AMY/s1600/Google%2BChromeScreenSnapz248.png" /&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;span class="largefont"&gt;Claudio Cherubino&lt;/span&gt; &amp;nbsp;   &lt;a class="alt" href="http://plus.google.com/+ClaudioCherubino" rel="me" target="_blank"&gt;profile&lt;/a&gt; | &lt;a class="alt" href="https://twitter.com/ccherubino" rel="me" target="_blank"&gt;twitter&lt;/a&gt; | &lt;a class="alt" href="http://www.claudiocherubino.it/" rel="me" target="_blank"&gt;blog&lt;/a&gt;
&lt;br /&gt;&lt;div class="bio"&gt;
&lt;br /&gt;Claudio is an engineer in the Google Drive Developer Relations team. Prior to Google, he worked as software developer, technology evangelist, community manager, consultant, technical translator and has contributed to many open-source projects. His current interests include Google APIs, new technologies and coffee.&lt;/div&gt;
&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GoogleAppsDeveloperBlog/~4/2CFqzFpVvzc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://googleappsdeveloper.blogspot.com/feeds/1437599555417407224/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1377183911445147227&amp;postID=1437599555417407224&amp;isPopup=true" title="27 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/1437599555417407224?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/1437599555417407224?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GoogleAppsDeveloperBlog/~3/2CFqzFpVvzc/introducing-actions-in-inbox-powered-by.html" title="Introducing Actions in the Inbox, powered by schemas" /><author><name>Google Apps Developer Blog Editor</name><uri>http://www.blogger.com/profile/07808045840831274565</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-l2vAzLwR7Ck/UZJ6FM69biI/AAAAAAAABCY/fydhxNXQnvg/s72-c/image00.png" height="72" width="72" /><thr:total>27</thr:total><feedburner:origLink>http://googleappsdeveloper.blogspot.com/2013/05/introducing-actions-in-inbox-powered-by.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkcEQHsycSp7ImA9WhBbFUo.&quot;"><id>tag:blogger.com,1999:blog-1377183911445147227.post-2248001256790601821</id><published>2013-05-14T17:33:00.000-07:00</published><updated>2013-05-14T17:33:21.599-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-05-14T17:33:21.599-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Apps Script" /><category scheme="http://www.blogger.com/atom/ns#" term="Google I/O" /><title>New Apps Script features at Google I/O—again!</title><content type="html">This Wednesday is the start of our annual developer conference, Google I/O, and we can’t wait to share a bunch of new features that will help developers do more with Apps Script. So let’s not wait! Check out these new features launching &lt;strong&gt;today&lt;/strong&gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Scripts in Google Docs&lt;/h3&gt;
Many of you have told us that you want to be able to &lt;a href="https://developers.google.com/apps-script/guides/docs"&gt;extend Google Docs&lt;/a&gt; just like Google Sheets, with custom menus, dialogs, and triggers. Starting today, you can do just that (plus custom sidebars, too). To learn more about Apps Script in Docs—including a couple of secret features that we can’t tell you about yet!—please tune into the live stream with me and Jonathan Rascher &lt;a href="https://developers.google.com/events/io/sessions/327928222"&gt;on Thursday at 3:30pm PT&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://2.bp.blogspot.com/-ve_C0r2TXFI/UY8zmEuVB0I/AAAAAAAABCI/iBedJnEkPfI/s1600/scripts-in-docs.png" imageanchor="1"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-ve_C0r2TXFI/UY8zmEuVB0I/AAAAAAAABCI/iBedJnEkPfI/s520/scripts-in-docs.png" /&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Forms Service / Scripts in Google Forms&lt;/h3&gt;
In response to another top request, you can now use the &lt;a href="https://developers.google.com/apps-script/reference/forms/"&gt;Forms Service&lt;/a&gt; to programmatically create and modify Google Forms, including triggers and a better way to respond to form submissions. (We’ve created a new &lt;a href="https://developers.google.com/apps-script/quickstart/forms"&gt;5-minute quickstart&lt;/a&gt; to get you going.) You can also extend the Google Forms editor with the same custom menus, dialogs, and sidebars as Google Docs. If you’re at I/O, learn how to build Forms with Apps Script by joining Eric Koleda and Matthew Ziegelbaum &lt;a href="https://developers.google.com/events/io/sessions/327782631"&gt;on Wednesday at 1:55pm PT&lt;/a&gt;.&lt;br /&gt;

&lt;br /&gt;
&lt;h3&gt;
Drive Service&lt;/h3&gt;
For those of you who use the DocsList Service to automate your Google Drive, a newer version is now available. &lt;a href="https://developers.google.com/apps-script/reference/drive/"&gt;Drive Service&lt;/a&gt; comes with new features like setting the owner of a file or folder or changing the sharing settings. We designed the new service from the ground up to make it easier to work with large numbers of files and also fixed a lot of bugs. If you’re at I/O, Arun Nagarajan and John McGowan will give you more insight into Drive integration &lt;a href="https://developers.google.com/events/io/sessions/325412094"&gt;on Thursday at 1:40pm PT&lt;/a&gt;.&lt;br /&gt;

&lt;br /&gt;
&lt;h3&gt;
Faster HtmlService&lt;/h3&gt;
At Google I/O 2012, we launched &lt;a href="https://developers.google.com/apps-script/guides/html-service"&gt;HtmlService&lt;/a&gt; to let you build custom user interfaces with secure client-side scripting. Starting today, you can &lt;a href="https://developers.google.com/apps-script/reference/html/html-output#setSandboxMode(SandboxMode)"&gt;enable an experimental version&lt;/a&gt; of the client-side sandbox that runs significantly faster in any browser that supports ECMAScript 5 strict mode.&lt;br /&gt;

&lt;br /&gt;
&lt;h3&gt;
Improved Authorization Flow and API Console Integration&lt;/h3&gt;
You’ve also told us that authorizing a script takes too many steps. Now, you can &lt;a href="https://developers.google.com/apps-script/scripts_google_accounts#authUpgrade"&gt;opt in to an experimental new authorization flow&lt;/a&gt; that requires fewer clicks. In addition, every script that uses the new flow &lt;a href="https://developers.google.com/apps-script/built_in_services#advanced_google_services"&gt;automatically creates a project in the Google APIs Console&lt;/a&gt;. This makes it much easier to use Google APIs that aren’t built in to Apps Script. To upgrade a script to the new flow, select &lt;strong&gt;File &amp;gt; Upgrade authorization experience&lt;/strong&gt;. If you’re at I/O, Arun Nagarajan and Christoph Schwab-Ganser will demonstrate the new flow in their session on using the YouTube Analytics API with Apps Script &lt;a href="https://developers.google.com/events/io/sessions/328316141"&gt;on Wednesday at 1:55pm PT&lt;/a&gt;.&lt;br /&gt;


&lt;p&gt;As you can see, we’ve been working hard to improve Apps Script for you. We hope you enjoy the new features!&lt;br /&gt;


&lt;br /&gt;&lt;table cellpadding="5" cellspacing="0"&gt;&lt;tbody&gt;
&lt;tr style="background-color: #f2f2f2;"&gt;&lt;td&gt;&lt;img class="profile" height="90/" src="http://1.bp.blogspot.com/-LavP1vCutPo/T-q1FW-Lo2I/AAAAAAAAAZg/GavUBu7obv8/s320/saurabh_photo.png" width="64" /&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;span class="largefont"&gt;Saurabh Gupta&lt;/span&gt; &amp;nbsp;   &lt;a class="alt" href="https://profiles.google.com/sg1705" rel="me" target="_blank"&gt;profile&lt;/a&gt; | &lt;a class="alt" href="http://twitter.com/gluemesh" rel="me" target="_blank"&gt;twitter&lt;/a&gt; | &lt;a class="alt" href="http://www.gluemesh.com/" rel="me" target="_blank"&gt;blog&lt;/a&gt;&lt;br /&gt;
&lt;div class="bio"&gt;
&lt;br /&gt;
As the product manager for Google Apps Script, Saurabh is responsible for Apps Script’s overall vision and direction.&lt;/div&gt;
&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;img src="http://feeds.feedburner.com/~r/GoogleAppsDeveloperBlog/~4/R_zbBkZt7d8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://googleappsdeveloper.blogspot.com/feeds/2248001256790601821/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1377183911445147227&amp;postID=2248001256790601821&amp;isPopup=true" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/2248001256790601821?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/2248001256790601821?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GoogleAppsDeveloperBlog/~3/R_zbBkZt7d8/new-apps-script-features-at-google.html" title="New Apps Script features at Google I/O—again!" /><author><name>Google Apps Developer Blog Editor</name><uri>http://www.blogger.com/profile/07808045840831274565</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-ve_C0r2TXFI/UY8zmEuVB0I/AAAAAAAABCI/iBedJnEkPfI/s72-c/scripts-in-docs.png" height="72" width="72" /><thr:total>5</thr:total><feedburner:origLink>http://googleappsdeveloper.blogspot.com/2013/05/new-apps-script-features-at-google.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEICRng-cCp7ImA9WhBUE0k.&quot;"><id>tag:blogger.com,1999:blog-1377183911445147227.post-4144793642442881299</id><published>2013-04-30T10:22:00.000-07:00</published><updated>2013-04-30T10:22:47.658-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-04-30T10:22:47.658-07:00</app:edited><title>New features for the Google Drive Realtime API</title><content type="html">&lt;p&gt;We recently announced the launch of the &lt;a href="http://googleappsdeveloper.blogspot.com/2013/03/build-collaborative-apps-with-google.html"&gt;Google Drive Realtime API&lt;/a&gt; that lets developers create collaborative apps with the same technology that powers &lt;a href="http://support.google.com/drive/bin/answer.py?hl=en&amp;amp;answer=49008"&gt;Google Docs, Sheets, and Slides&lt;/a&gt;. Today we’ve added a couple of small, but very useful, features that let developers do even more with the &lt;a href="https://developers.google.com/drive/realtime"&gt;Realtime API&lt;/a&gt;: &lt;a href="https://developers.google.com/drive/realtime/reference/gapi.drive.realtime.Model#gapi.drive.realtime.Model.undo"&gt;undo&lt;/a&gt; and &lt;a href="https://developers.google.com/drive/realtime/reference/gapi.drive.realtime.Model#gapi.drive.realtime.Model.redo"&gt;redo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The new undo and redo features provide developers a way to easily undo (or redo) local changes without worrying about the complexities that can happen in a collaborative environment. The Realtime API automatically resolves potential conflicts from overlapping edits by collaborators to undo only the local changes.&lt;/p&gt;

&lt;p&gt;The functions themselves are very simple to implement. The following code demonstrates how straightforward adding this functionality to your app can be:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;if (model.canUndo) {
  model.undo();
}&lt;/pre&gt;

&lt;p&gt;You could connect this code directly to an undo button in your app’s UI to undo the last change a local user made. No extra hard work required!&lt;/p&gt;

&lt;p&gt;Undo and redo also come with an associated event emitted by the model class that lets you know when the features are available. You just need to attach an event listener to the model and wire up the appropriate UI changes to enable/disable undo/redo buttons. For example, you could add two buttons inside the &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; tag of your HTML document:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;&amp;lt;button id="undoButton" disabled&amp;gt;Undo&amp;lt;/button&amp;gt;
&amp;lt;button id="redoButton" disabled&amp;gt;Redo&amp;lt;/button&amp;gt;&lt;/pre&gt;

&lt;p&gt;Then, add the following code inside the onFileLoaded callback inside your script to connect the logic to the buttons:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;var model = doc.getModel();
var undoButton = document.getElementById('undoButton');
var redoButton = document.getElementById('redoButton');

undoButton.onclick = function(e) {
  model.undo();
};
redoButton.onclick = function(e) {
  model.redo();
};&lt;/pre&gt;

&lt;p&gt;Then add an event handler to enable and disable the buttons when local changes are available:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;var onUndoRedoStateChanged = function(e) {
  undoButton.disabled = !e.canUndo;
  redoButton.disabled = !e.canRedo;
};
model.addEventListener(gapi.drive.realtime.EventType.UNDO_REDO_STATE_CHANGED, onUndoRedoStateChanged);&lt;/pre&gt;

&lt;p&gt;For a complete example of this implementation, see the &lt;a href="https://developers.google.com/drive/realtime/realtime-quickstart"&gt;Realtime Quickstart&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The Realtime API makes implementing undo/redo features very straightforward for most applications. For more information, see the &lt;a href="https://developers.google.com/drive/realtime"&gt;Realtime API documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;
&lt;table cellpadding="5" cellspacing="0"&gt;&lt;tbody&gt;
&lt;tr style="background-color: #f2f2f2;"&gt;&lt;td&gt;&lt;img class="profile" src="http://2.bp.blogspot.com/-UMQBQYQv9Jw/UX_5ALDI2lI/AAAAAAAAADw/ONOG1coddoE/s320/greg_knoke.jpg" /&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;span class="largefont"&gt;Greg Knoke&lt;/span&gt;   &lt;a class="alt" href="https://plus.google.com/109481088328189052918?rel=author" target="_blank"&gt;Google+&lt;/a&gt;
&lt;div class="bio"&gt;
&lt;br /&gt;
Greg Knoke is a technical writer in the Google Drive Developer Relations Team. Prior to joining Google, he worked as a scientist developing image and signal processing algorithms. His current interests include new technologies, content management, information architecture, cooking, music, and photography.&lt;/div&gt;
&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GoogleAppsDeveloperBlog/~4/Uf2_gJ5Do_w" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://googleappsdeveloper.blogspot.com/feeds/4144793642442881299/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1377183911445147227&amp;postID=4144793642442881299&amp;isPopup=true" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/4144793642442881299?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/4144793642442881299?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GoogleAppsDeveloperBlog/~3/Uf2_gJ5Do_w/new-features-for-google-drive-realtime.html" title="New features for the Google Drive Realtime API" /><author><name>Greg Knoke</name><uri>http://www.blogger.com/profile/13138268226403899923</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-UMQBQYQv9Jw/UX_5ALDI2lI/AAAAAAAAADw/ONOG1coddoE/s72-c/greg_knoke.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://googleappsdeveloper.blogspot.com/2013/04/new-features-for-google-drive-realtime.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A04NR3c8fSp7ImA9WhBUEkg.&quot;"><id>tag:blogger.com,1999:blog-1377183911445147227.post-2707907650719831241</id><published>2013-04-29T11:26:00.001-07:00</published><updated>2013-04-29T11:26:36.975-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-04-29T11:26:36.975-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Apps Script" /><category scheme="http://www.blogger.com/atom/ns#" term="Guest Post" /><title>How Apps Script Makes Classroom Observation Quicker and Easier</title><content type="html">&lt;p&gt;&lt;i&gt;Editor’s Note: Guest author Martin Hawksey is an advisor at the &lt;a href="http://jisc.cetis.ac.uk/"&gt;Jisc Centre for Educational Technology and Interoperability Standards&lt;/a&gt;. — Dan Lazin&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;When I started looking at Google Apps Script in 2010, one of the things that attracted me was the ease with which a non-developer like me could start customising Google Apps with only a few lines of code. Since then, the rich community of users and examples has continued to grow, and I’ve built &lt;a href="http://mashe.hawksey.info/2010/11/eventmanagerv3/"&gt;event booking systems&lt;/a&gt;, &lt;a href="http://mashe.hawksey.info/2012/06/using-google-apps-script-to-fast-track-student-feedback-behind-the-code/"&gt;entire student feedback solutions&lt;/a&gt;, and even &lt;a href="http://mashe.hawksey.info/2012/12/open-badges-issuer-gadget-google-sites/"&gt;integrated with Mozilla Open Badges&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Recently, Justin Marckel, the assistant principal at Cornatzer Elementary School in North Carolina, asked for help in modifying one of my existing Apps Script examples. Justin was recording teachers’ classroom activities using a Google Form, then manually copying and pasting data into separate spreadsheets for each teacher to review. Justin wanted to know whether there was a way for a Google Form to store the results in a master spreadsheet, then filter results to each teacher’s spreadsheet.&lt;/p&gt;

&lt;p&gt;The basic pseudocode would be:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;on form submit
  if teacher’s spreadsheet doesn’t exist, then
    create spreadsheet
    add teacher as viewer
    store id
  else
    get id
    open teacher’s spreadsheet
  copy values to teacher’s spreadsheet&lt;/pre&gt;

&lt;p&gt;Here’s a closer look at each of the steps.&lt;/p&gt;

&lt;h3&gt;Handling a form submission event&lt;/h3&gt;

&lt;p&gt;Apps Script offers three triggers specific to Google Sheets: “on open,” “on edit,” and “on form submit.” Looking at the &lt;a href="https://developers.google.com/apps-script/understanding_events"&gt;Understanding Events documentation&lt;/a&gt;, we can see that a form submit trigger gives us a few options for how to pull the submitted values out of the event parameter (usually called e). We can get the data as an array via e.values, a Range object via e.range, or a JavaScript object that pairs the form questions with the respondent’s answers via e.namedValues. In this project, the e.values array is most convenient, and it will look something like this:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;['2010/03/12 15:00', 'bob@example.com', 'Bob', '27', 'Susan', '25']&lt;/pre&gt;

&lt;p&gt;First, though, we have to add the form-submission trigger. The user could add it manually from the script editor’s Resources menu, but in this case, let’s &lt;a href="https://developers.google.com/apps-script/managing_triggers_programmatically"&gt;manage triggers programmatically&lt;/a&gt;:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;function setup(){
 if (ScriptApp.getScriptTriggers().length === 0) {
   ScriptApp.newTrigger('doOnFormSumbit')
       .forSpreadsheet(SpreadsheetApp.getActiveSpreadsheet())
       .onFormSubmit()
       .create();
 }
}&lt;/pre&gt;

&lt;h3&gt;Creating and managing permissions on a spreadsheet&lt;/h3&gt;

&lt;p&gt;One of the big advantages Apps Script is that you’re automatically working in a Google-authenticated environment. The result is that you can &lt;a href="https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet-app#create(String)"&gt;programmatically create a new spreadsheet&lt;/a&gt; with one line of code, then add a teacher as a viewer in just one more line:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;var newSS = SpreadsheetApp.create('Spreadsheet Name');
newSS.addViewer('email-address-of-teacher');&lt;/pre&gt;

&lt;h3&gt;Writing data to a spreadsheet&lt;/h3&gt;

&lt;p&gt;Writing data to a sheet requires more than a one-liner just because we need to specify which cells to write to. The &lt;code&gt;&lt;a href="https://developers.google.com/apps-script/reference/spreadsheet/range#setValues(Object)"&gt;Range.setValues()&lt;/a&gt;&lt;/code&gt; method expects a 2D array; because we’ve already retrieved the response to the form as an array, it’s easy to throw those values into a row of cells:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;var destSS = SpreadsheetApp.openById(id); // open teacher spreadsheet
var destSheet = destSS.getSheets()[0]; // grab first sheet
var insertRow = destSheet.getLastRow() + 1; // next row to enter data
destSheet.getRange(insertRow, 1, 1, e.values.length)
   .setValues([e.values]);&lt;/pre&gt;

&lt;h3&gt;Simple, effective and efficient&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.google.com/a/google.com/spreadsheet/ccc?key=0AqGkLMU9sHmLdFJ2VjNpYnlvb01rMVVnaGp2R19vVVE#gid=0"&gt;The completed project is here&lt;/a&gt;. The bulk of the form-submission handling (including error logging) happens in around 50 lines of code, and I was able to complete the project within an hour. Now Justin no longer needs to copy, paste, and set up separate spreadsheets, potentially saving him hours of work. Justin recently contacted me to say:&lt;/p&gt;

&lt;p&gt;&lt;i&gt;“We have successfully used our program over the past couple of months to provide teachers with meaningful and efficient feedback. It has been successful at several other schools as well, and I got word today that our school district is looking at adopting it as a district-wide tool.”&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;This is just one of a growing number of examples of how Google Apps Script is directly benefitting educators by allowing custom solutions with the security, convenience, and power of Google Apps.&lt;/p&gt;

&lt;table cellpadding="5" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr style="background-color: #f2f2f2;"&gt;&lt;td&gt;&lt;img class="profile" src="http://4.bp.blogspot.com/-vjC3oDkDG5g/UX64z_SHNCI/AAAAAAAABB0/UkfdyqEmScs/s320/martin_hawksey.jpg" /&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;span class="largefont"&gt;Martin Hawksey&lt;/span&gt; &amp;nbsp;   &lt;a class="alt" href="https://plus.google.com/114662816634467534305/posts" rel="me" target="_blank"&gt;profile&lt;/a&gt; | &lt;a class="alt" href="https://twitter.com/mhawksey" rel="me" target="_blank"&gt;twitter&lt;/a&gt; | &lt;a class="alt" href="http://mashe.hawksey.info/" rel="me" target="_blank"&gt;blog&lt;/a&gt;&lt;br /&gt;&lt;div class="bio"&gt;&lt;br /&gt;Martin is an advisor at the &lt;a href="http://jisc.cetis.ac.uk/"&gt;Jisc Centre for Educational Technology and Interoperability Standards (CETIS)&lt;/a&gt;, a national advisory and innovation centre that works on on educational technology and standards for the UK Higher Education and Post-16 Education sectors. Martin is an active contributor to the Apps Script community and regularly shares projects on his blog, &lt;a href="http://mashe.hawksey.info/category/google/google-apps-script/"&gt;MASHe&lt;/a&gt;.&lt;/div&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;img src="http://feeds.feedburner.com/~r/GoogleAppsDeveloperBlog/~4/OWF75az6H7A" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://googleappsdeveloper.blogspot.com/feeds/2707907650719831241/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1377183911445147227&amp;postID=2707907650719831241&amp;isPopup=true" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/2707907650719831241?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/2707907650719831241?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GoogleAppsDeveloperBlog/~3/OWF75az6H7A/how-apps-script-makes-classroom.html" title="How Apps Script Makes Classroom Observation Quicker and Easier" /><author><name>Google Apps Developer Blog Editor</name><uri>http://www.blogger.com/profile/07808045840831274565</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-vjC3oDkDG5g/UX64z_SHNCI/AAAAAAAABB0/UkfdyqEmScs/s72-c/martin_hawksey.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://googleappsdeveloper.blogspot.com/2013/04/how-apps-script-makes-classroom.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEEDQHk4eip7ImA9WhBWEU0.&quot;"><id>tag:blogger.com,1999:blog-1377183911445147227.post-4156700847897990926</id><published>2013-04-04T12:11:00.000-07:00</published><updated>2013-04-04T12:11:11.732-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-04-04T12:11:11.732-07:00</app:edited><title>More ways for apps to write to Drive</title><content type="html">&lt;p&gt;Today we’re introducing two new ways for apps to build even richer integrations with Drive: app data folders and custom properties.&lt;/p&gt;

&lt;p&gt;In order to run smoothly, your app may depend on data it stores in Drive. But occasionally, users may accidentally move or delete the very file or folder your app needs to function.  The &lt;a href="https://developers.google.com/drive/appdata"&gt;app data folder&lt;/a&gt; is a special folder in Drive that can only be accessed by your app.  The app folder’s content is hidden from the user and from other apps, making it ideal for storing configuration files, app state data, or any other files that the user should not modify.&lt;/p&gt;

&lt;p&gt;Although users cannot see individual files in the app data folder, they are able to see how much app data your app is using and clear that data in the Manage Apps dialog.&lt;/p&gt;

&lt;div style="text-align:center;"&gt;
&lt;p/&gt;
&lt;img style="border: none;" border="0" src="http://2.bp.blogspot.com/-VQoNJ8pYehQ/UV3PnplZprI/AAAAAAAABBk/s5S6InVFUX4/s480/image00.png" /&gt;
&lt;/div&gt;

&lt;p&gt;Apps can also now add custom properties to any Drive file.  The new properties collection gives your app the power to create searchable fields that are private to your app or shared across apps.  For example, a classroom app could keep track of the grade for a document or a project management app could keep track of the current status of a document going through a review process.&lt;/p&gt;


&lt;p&gt;To learn more check out the technical documentation for both &lt;a href="https://developers.google.com/drive/appdata"&gt;app data folders&lt;/a&gt; and &lt;a href="https://developers.google.com/drive/properties"&gt;custom properties&lt;/a&gt;, and if you have questions don’t hesitate to post on &lt;a href="http://stackoverflow.com/questions/tagged/google-drive-sdk"&gt;StackOverflow&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;
&lt;table cellpadding="5" cellspacing="0"&gt;&lt;tbody&gt;
&lt;tr style="background-color: #f2f2f2;"&gt;&lt;td&gt;&lt;img class="profile" src="http://sites.google.com/site/developeradvocates/image/nicolas_garnier.png" /&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;span class="largefont"&gt;Nicolas Garnier&lt;/span&gt;   &lt;a class="alt" href="https://plus.google.com/108635752367054807758?rel=author" target="_blank"&gt;Google+&lt;/a&gt; | &lt;a class="alt" href="http://twitter.com/nivco" rel="me" target="_blank"&gt;Twitter&lt;/a&gt;&lt;br /&gt;
&lt;div class="bio"&gt;
&lt;br /&gt;
Nicolas Garnier joined Google’s Developer Relations in 2008 and lives in Zurich. He is a Developer Advocate for Google Drive and Google Apps. Nicolas is also the lead engineer for the &lt;a href="https://developers.google.com/oauthplayground/" target="_blank"&gt;OAuth 2.0 Playground&lt;/a&gt;.&lt;/div&gt;
&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GoogleAppsDeveloperBlog/~4/K89P31zFfUQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://googleappsdeveloper.blogspot.com/feeds/4156700847897990926/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1377183911445147227&amp;postID=4156700847897990926&amp;isPopup=true" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/4156700847897990926?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/4156700847897990926?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GoogleAppsDeveloperBlog/~3/K89P31zFfUQ/more-ways-for-apps-to-write-to-drive.html" title="More ways for apps to write to Drive" /><author><name>Google Apps Developer Blog Editor</name><uri>http://www.blogger.com/profile/07808045840831274565</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-VQoNJ8pYehQ/UV3PnplZprI/AAAAAAAABBk/s5S6InVFUX4/s72-c/image00.png" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://googleappsdeveloper.blogspot.com/2013/04/more-ways-for-apps-to-write-to-drive.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk4DR30_fSp7ImA9WhBXFUo.&quot;"><id>tag:blogger.com,1999:blog-1377183911445147227.post-3837636497204509364</id><published>2013-03-29T09:36:00.000-07:00</published><updated>2013-03-29T09:36:16.345-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-03-29T09:36:16.345-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Apps Script" /><category scheme="http://www.blogger.com/atom/ns#" term="Guest Post" /><title>Apps Script helps name Pluto's new moons</title><content type="html">&lt;a href="http://3.bp.blogspot.com/-ime5oRpytzc/UVXBUHLXIbI/AAAAAAAABBM/7vhfVXv0IY8/s1600/pluto1.png" imageanchor="1" &gt;&lt;img border="0" width=520 src="http://3.bp.blogspot.com/-ime5oRpytzc/UVXBUHLXIbI/AAAAAAAABBM/7vhfVXv0IY8/s520/pluto1.png" /&gt;&lt;/a&gt;

&lt;p&gt;&lt;i&gt;Editor’s Note: Guest author Mark Showalter is a Senior Research Scientist at the &lt;a href="http://www.seti.org/"&gt;SETI Institute&lt;/a&gt;. — Arun Nagarajan&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;In 2011 and 2012, while studying the region around Pluto with the Hubble Space Telescope, I discovered the dwarf planet’s fourth and fifth known moons. Like all new astronomical objects, they started out with rather prosaic names — “S/2011 (134340) 1” and “S/2012 (134340) 1”, or, for short, P4 and P5.&lt;/p&gt;

&lt;p&gt;I soon found my inbox stuffed with hundreds of naming suggestions. With so much interest, it didn’t seem fair to leave the job to just a handful of scientists. Instead, we decided to &lt;a href="http://www.plutorocks.com/"&gt;let the public propose and vote on the names of Pluto’s moons&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We knew that the web servers at the SETI Institute, my research home, could never handle the bandwidth required for such a task. However, the Institute has built strong relationships with Google through &lt;a href="https://plus.google.com/+SETIInstitute/posts"&gt;our extensive use of G+&lt;/a&gt;, and our friends there were thrilled to let us use Google services for the demanding task. I asked my husband Frank Yellin, who works on the Gmail team, for help in setting up the forms and collecting the data. Google Forms and Google Sheets were obvious choices, but with the volume of contributions and votes we were expecting, we knew we’d need programmatic help checking for duplicate nominees, filtering out inappropriate names, and tallying the votes.&lt;/p&gt;

&lt;p&gt;Frank is a longtime Java engineer, so he tried a Java solution first. As the votes started to pour in at the rate of several per second, however, it became clear that the program could barely keep pace. Votes were coming in almost as fast as they were being downloaded and tallied. In a panic, Frank realized it was time to learn Apps Script — in fact, time to learn JavaScript altogether.&lt;/p&gt;

&lt;p&gt;With some help from his colleagues (“How do I split a string?” “How do I make a hash table?”), he turned the project around in a few hours. Processing that had taken tens of minutes using Java took mere seconds in Apps Script, since nothing but the results ever had to leave the data center.&lt;/p&gt;

&lt;p&gt;We were right to be prepared. By the time we closed the write-in ballot, we had received 30,000 write-in nominees and more than 450,000 votes.&lt;/p&gt;

&lt;p&gt;We are now using the results of the poll to support our proposal for the formal names of P4 and P5. That decision is currently in the hands of the International Astronomical Union. When the final decision is made, Pluto and Charon and Nix and Hydra will be joined by two more representatives of the ancient underworld.&lt;/p&gt;

&lt;table cellpadding="5" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr style="background-color: #f2f2f2;"&gt;&lt;td&gt;&lt;img class="profile" src="http://1.bp.blogspot.com/-ayZceyoEbso/UVXBUFRuHjI/AAAAAAAABBQ/10P5Eh4ZYrs/s320/pluto2.jpg" /&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;span class="largefont"&gt;Dr. Mark Showalter&lt;/span&gt; &amp;nbsp;   &lt;a class="alt" href="http://www.seti.org/users/mshowalter" rel="me" target="_blank"&gt;profile&lt;/a&gt;&lt;br /&gt;&lt;div class="bio"&gt;&lt;br /&gt;Planetary scientist Mark Showalter is a Senior Research Scientist at the &lt;a href="http://www.seti.org/"&gt;SETI Institute&lt;/a&gt;. His primary interest in the dynamics of planetary rings. To date, this interest has led him to discover five new moons and three new rings.
&lt;/div&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;img src="http://feeds.feedburner.com/~r/GoogleAppsDeveloperBlog/~4/5S1omYPM6uo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://googleappsdeveloper.blogspot.com/feeds/3837636497204509364/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1377183911445147227&amp;postID=3837636497204509364&amp;isPopup=true" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/3837636497204509364?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/3837636497204509364?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GoogleAppsDeveloperBlog/~3/5S1omYPM6uo/apps-script-helps-name-plutos-new-moons.html" title="Apps Script helps name Pluto's new moons" /><author><name>Google Apps Developer Blog Editor</name><uri>http://www.blogger.com/profile/07808045840831274565</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-ime5oRpytzc/UVXBUHLXIbI/AAAAAAAABBM/7vhfVXv0IY8/s72-c/pluto1.png" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://googleappsdeveloper.blogspot.com/2013/03/apps-script-helps-name-plutos-new-moons.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkACRnc9eCp7ImA9WhBXFUo.&quot;"><id>tag:blogger.com,1999:blog-1377183911445147227.post-9112232121404878954</id><published>2013-03-25T11:29:00.000-07:00</published><updated>2013-03-29T09:32:47.960-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-03-29T09:32:47.960-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Apps Script" /><category scheme="http://www.blogger.com/atom/ns#" term="Guest Post" /><title>Hack to School</title><content type="html">&lt;p&gt;&lt;i&gt;Editor’s Note: Guest author Andrew Stillman is a teacher who works at &lt;a href="http://www.newvisions.org/"&gt;New Visions for Public Schools&lt;/a&gt;, a non-profit that provides direct support services to 76 New York City high schools. — Arun Nagarajan&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;On March 16th, as a green tide tide of college students flowed into Manhattan for a day of rousing revelry, more than 50 young coders from New York-area computer science programs and 30 teachers were drawn instead to Kean University in New Jersey by the gravity of &lt;a href="http://www.hack4ed.org/"&gt;St. Hacktrick’s Day&lt;/a&gt;, our first Apps Script for EDU Codeathon. Inspired by the viral popularity of the &lt;a href="http://www.edcode.org/projects"&gt;Flubaroo&lt;/a&gt;, &lt;a href="http://www.youpd.org/doctopus"&gt;Doctopus&lt;/a&gt;, and &lt;a href="http://www.youpd.org/autocrat"&gt;autoCrat&lt;/a&gt; scripts for teachers, St. Hacktrick’s Day aimed to pair coders with educators to produce more free, smart tools for education.&lt;/p&gt;

&lt;br&gt;

&lt;a href="http://4.bp.blogspot.com/-YgvmqROWN2k/UVCRzC9Y07I/AAAAAAAABAE/LeY7QCrh3tA/s1600/sthacks1.JPG" imageanchor="1" style=""&gt;&lt;img border="0" width=520 src="http://4.bp.blogspot.com/-YgvmqROWN2k/UVCRzC9Y07I/AAAAAAAABAE/LeY7QCrh3tA/s520/sthacks1.JPG" /&gt;&lt;/a&gt;
&lt;em&gt;Teacher Daniel Scibienski works as an elementary ESL teacher in NJ. He helped organize and emcee the event, and was on the winning team that built a picture-prompt generator for Google Docs.&lt;/em&gt;

&lt;p&gt;Most of the student scripters were on their first day of spring break, making our huge turnout for this event all the more remarkable. Product designers — all working educators who took time out on a Saturday — traveled from as far north as Ulster County, NY and as far south as Virginia, while we had others who joined teams via G+ Hangouts from Singapore, Montreal, Vancouver, and London.&lt;/p&gt;

&lt;br&gt;

&lt;a href="http://3.bp.blogspot.com/-Z67fTsQeLtU/UVCUWxw9EVI/AAAAAAAABA8/LIoPO2no7qI/s1600/sthacks2.JPG" imageanchor="1" style=""&gt;&lt;img border="0" width=520 src="http://3.bp.blogspot.com/-Z67fTsQeLtU/UVCUWxw9EVI/AAAAAAAABA8/LIoPO2no7qI/s520/sthacks2.JPG" /&gt;&lt;/a&gt;
&lt;em&gt;This team built a class-roster Google Site replicator using Apps Script, cookies, and Coke. Their EDU design partner was located in the UK!&lt;/em&gt;

&lt;p&gt;Unlike a typical hackathon, teams weren’t simply building their own ideas — instead, to ensure their scripts would be truly useful in the classroom, we solicited project proposals through a &lt;a href="http://www.google.com/moderator/#16/e=20425d"&gt;Google Moderator board&lt;/a&gt;. By the day of the event, we had 48 ideas with 187 votes from educators around the world.&lt;/p&gt;

&lt;p&gt;In all, 17 teams built demo-ready prototypes in less than 6 hours of coding. The Apps Script team rounded up a few &lt;a href="http://www.google.com/nexus/7/"&gt;Nexus 7 tablets&lt;/a&gt; for the winners below and invited them to present their projects to the Google Docs engineering team:&lt;/p&gt;

&lt;br&gt;

&lt;p&gt;&lt;a href="http://3.bp.blogspot.com/-Eq19q71tRYs/UVCRzCBIlBI/AAAAAAAABAM/Ba2aWKANN8M/s1600/sthacks3.png" imageanchor="1" style=""&gt;&lt;img border="0" width=520 src="http://3.bp.blogspot.com/-Eq19q71tRYs/UVCRzCBIlBI/AAAAAAAABAM/Ba2aWKANN8M/s520/sthacks3.png" /&gt;&lt;/a&gt;
&lt;strong&gt;Popular vote:&lt;/strong&gt; Picture Prompt Generator&lt;br&gt;
&lt;strong&gt;Summary:&lt;/strong&gt; Inserts kid-friendly pictures from Google Image Search into student documents. Elementary students then write stories based on the visual prompts.&lt;br&gt;
&lt;strong&gt;Design:&lt;/strong&gt; Daniel Scibienski&lt;br&gt;
&lt;strong&gt;Code:&lt;/strong&gt; Ashish Nandwani and Krutika Shah&lt;/p&gt;

&lt;br&gt;

&lt;p&gt;&lt;a href="http://3.bp.blogspot.com/-T2ljU0x0JYo/UVCRzaEsANI/AAAAAAAABAU/PnqooTzUPMU/s1600/sthacks4.jpg" imageanchor="1" style=""&gt;&lt;img border="0" width=520 src="http://3.bp.blogspot.com/-T2ljU0x0JYo/UVCRzaEsANI/AAAAAAAABAU/PnqooTzUPMU/s520/sthacks4.jpg" /&gt;&lt;/a&gt;
&lt;strong&gt;Judges' choice:&lt;/strong&gt; Plagiarism Detector&lt;br&gt;
&lt;strong&gt;Summary:&lt;/strong&gt; Uses a similarity algorithm to rank Google Documents by originality.&lt;br&gt;
&lt;strong&gt;Design and code:&lt;/strong&gt; Alice Lin, Basim Baig, and Jackie Wei (Stony Brook University)&lt;/p&gt;

&lt;br&gt;

&lt;p&gt;&lt;a href="http://2.bp.blogspot.com/-q5bmOBKXyi0/UVCRz2t9PbI/AAAAAAAABAc/Z8e7zomzTPs/s1600/sthacks6.png" imageanchor="1" style=""&gt;&lt;img border="0" width=520 src="http://2.bp.blogspot.com/-q5bmOBKXyi0/UVCRz2t9PbI/AAAAAAAABAc/Z8e7zomzTPs/s520/sthacks6.png" /&gt;&lt;/a&gt;
&lt;strong&gt;Judges' choice:&lt;/strong&gt; Unpivot Google Form Data&lt;br&gt;
&lt;strong&gt;Summary:&lt;/strong&gt; Removes duplicates from Google Form data and transforms it for use in a pivot table.&lt;br&gt;
&lt;strong&gt;Design:&lt;/strong&gt; Ron Turchyniak&lt;br&gt;
&lt;strong&gt;Code:&lt;/strong&gt; Andrew Ireland, Sangwook Lee, and Steve Byung Park (Stony Brook University)&lt;/p&gt;

&lt;br&gt;

&lt;p&gt;Teams have been asked to open-source their code and donate it to &lt;a href="http://www.newvisions.org/"&gt;New Visions for Public Schools&lt;/a&gt;, the support organization I work for, and to consider improving their projects for use by educators everywhere. &lt;a href="http://www.hack4ed.org/"&gt;We’ll keep you posted&lt;/a&gt; as these resources become available.&lt;/p&gt;

&lt;p&gt;Big thanks to our participants, to organizers &lt;a href="https://plus.google.com/116831697717996851812"&gt;Meredith Martin&lt;/a&gt;, &lt;a href="https://plus.google.com/102815233975205001741"&gt;Dave Zirkle&lt;/a&gt;, &lt;a href="https://plus.google.com/105478796255115712747"&gt;Daniel Scibienski&lt;/a&gt;, &lt;a href="https://plus.google.com/106539410272554929071"&gt;Emily Graves&lt;/a&gt;, &lt;a href="https://plus.google.com/100751006330067336488"&gt;Diana Potts&lt;/a&gt;, &lt;a href="https://plus.google.com/113091647598120328318"&gt;Lisa Thumann&lt;/a&gt;, &lt;a href="https://plus.google.com/104798296922402863492"&gt;Andrew Carle&lt;/a&gt;, and to Google’s &lt;a href="https://plus.google.com/117678608428606781684"&gt;Arun Nagarajan&lt;/a&gt;, &lt;a href="https://plus.google.com/105831704374179338116"&gt;Saurabh Gupta&lt;/a&gt;, and &lt;a href="https://plus.google.com/102311875004581334954"&gt;Zach Yeskel.&lt;/a&gt;&lt;/p&gt;

&lt;table cellpadding="5" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr style="background-color: #f2f2f2;"&gt;&lt;td&gt;&lt;img class="profile" src="http://1.bp.blogspot.com/-Y1D_WJfUQAs/UVCUFlSx1eI/AAAAAAAABA0/Rr6PaUS1mOQ/s320/sthacks7.jpg" /&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;span class="largefont"&gt;Andrew Stillman&lt;/span&gt; &amp;nbsp;   &lt;a class="alt" href="https://plus.google.com/114670488345865665282/posts" rel="me" target="_blank"&gt;profile&lt;/a&gt;&lt;br /&gt;&lt;div class="bio"&gt;&lt;br /&gt;Andrew Stillman is a career STEM educator who works as Program Officer for Digital Instruction at &lt;a href="http://www.newvisions.org/"&gt;New Visions for Public Schools&lt;/a&gt;, a non-profit that provides direct support services to 76 New York City high schools. Andrew founded &lt;a href="http://youpd.org/"&gt;YouPD.org&lt;/a&gt; and has written a number of popular Apps Scripts for schools designed to improve efficacy through better workflows, communications, and data management in Google Apps.
&lt;/div&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;img src="http://feeds.feedburner.com/~r/GoogleAppsDeveloperBlog/~4/KARjv5W5Xx0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://googleappsdeveloper.blogspot.com/feeds/9112232121404878954/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1377183911445147227&amp;postID=9112232121404878954&amp;isPopup=true" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/9112232121404878954?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/9112232121404878954?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GoogleAppsDeveloperBlog/~3/KARjv5W5Xx0/hack-to-school.html" title="Hack to School" /><author><name>Google Apps Developer Blog Editor</name><uri>http://www.blogger.com/profile/07808045840831274565</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-YgvmqROWN2k/UVCRzC9Y07I/AAAAAAAABAE/LeY7QCrh3tA/s72-c/sthacks1.JPG" height="72" width="72" /><thr:total>4</thr:total><feedburner:origLink>http://googleappsdeveloper.blogspot.com/2013/03/hack-to-school.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE8MRH88fyp7ImA9WhBQF0Q.&quot;"><id>tag:blogger.com,1999:blog-1377183911445147227.post-317334457163160189</id><published>2013-03-19T09:01:00.000-07:00</published><updated>2013-03-20T08:21:25.177-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-03-20T08:21:25.177-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Drive SDK" /><title>Build collaborative apps with Google Drive Realtime API</title><content type="html">Google Drive lets users create &lt;a href="http://support.google.com/drive/bin/answer.py?hl=en&amp;amp;answer=49008"&gt;Docs, Sheets, and Slides&lt;/a&gt;, collaborate on them in real time, and have their changes saved instantly and automatically. With the new &lt;a href="https://developers.google.com/drive/realtime"&gt;Google Drive Realtime API&lt;/a&gt;, you can now easily add the same real-time collaboration that powers Google Drive to your own apps. This new API handles network communication, storage, presence, conflict resolution, and other collaborative details so you can focus on building great apps.&lt;br /&gt;
&lt;br /&gt;
Developing for the Drive Realtime API is almost as simple as working with local objects. The API provides collaborative versions of familiar data objects such as maps, lists, strings, and JSON values and automatically synchronizes and stores modifications to these objects. Your application reads from and writes to these objects like any other local object. Change event handlers can be added to collaborative objects so that your app can react to changes from other collaborators.&lt;br /&gt;
&lt;br /&gt;
Because the Drive Realtime API is based on &lt;a href="http://en.wikipedia.org/wiki/Operational_transformation"&gt;operational transformation (OT)&lt;/a&gt;, local changes are reflected instantly, even on high-latency networks. The Drive Realtime API automatically transforms changes to the data model so that every collaborator stays in sync.&lt;br /&gt;
&lt;br /&gt;
If basic collections aren't enough for your application, the Drive Realtime API supports custom objects and references, including trees and arbitrary graph structures. As with other collaborative objects, the Drive Realtime API automatically synchronizes these objects with other collaborators and stores them in Drive.&lt;br /&gt;
&lt;br /&gt;
Because presence is important in collaborative applications, the Drive Realtime API also &lt;a href="https://developers.google.com/drive/realtime/reference/gapi.drive.realtime.Document#getCollaborators"&gt;keeps track of who is connected&lt;/a&gt; to your application and provides your app with events for when collaborators join, leave, or make changes.&lt;br /&gt;
&lt;div style="text-align: center;"&gt;
&lt;img src="http://4.bp.blogspot.com/-qFtKuBsMOfI/UUNg_v0AJnI/AAAAAAAAA_U/i2G61boQmSA/s480/image01.png" style="border: none;" /&gt;
&lt;br /&gt;
&lt;i&gt;Widget using the Drive Realtime API and showing the collaborators on a document&lt;/i&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;a href="https://neutron-drive.appspot.com/edit"&gt;Neutron Drive&lt;/a&gt;, &lt;a href="http://gantter.com/"&gt;Gantter&lt;/a&gt; and &lt;a href="https://rt.draw.io/"&gt;draw.io&lt;/a&gt; have enabled realtime collaboration in their apps using the Google Drive Realtime API. Check out these apps to see the Drive Realtime API in action.

&lt;br /&gt;
&lt;h2&gt;
Collaborative code editing with Neutron Drive&lt;/h2&gt;
&lt;a href="https://neutron-drive.appspot.com/edit"&gt;Neutron Drive&lt;/a&gt; is an online editor for text and source code files stored in Google Drive. You can now collaboratively edit any text or source code files stored in Drive and get a collaboration experience similar to Google Docs — shared typing, a view of active collaborators, cursor positioning, and selected text.  This all comes in addition to the syntax highlighting and other advanced features offered by Neutron Drive. To learn more, watch the video below:&lt;br /&gt;
&lt;br /&gt;
&lt;iframe allowfullscreen="" frameborder="0" height="270" src="http://www.youtube.com/embed/_JVK9j1RrV0" width="480"&gt;&lt;/iframe&gt;

&lt;br /&gt;
&lt;h2&gt;
Collaborative project scheduling with Gantter&lt;/h2&gt;
&lt;a href="http://gantter.com/"&gt;Gantter&lt;/a&gt; is a free online project scheduling tool and Gantt diagram editor. It now allows you to collaboratively — and in real time — work on your project schedules. It even features an embedded chat powered by the Drive Realtime API. Watch the video below to see Gantter’s new realtime collaboration features in action.&lt;br /&gt;
&lt;br /&gt;
&lt;iframe allowfullscreen="" frameborder="0" height="270" src="http://www.youtube.com/embed/XxVkeK9j3Wg" width="480"&gt;&lt;/iframe&gt;

&lt;br /&gt;
&lt;h2&gt;
Collaborative diagraming with draw.io&lt;/h2&gt;
&lt;a href="https://rt.draw.io/"&gt;draw.io&lt;/a&gt; is a diagraming application that enables you to draw a wide variety of diagrams such as flowcharts, UML diagrams and even electronic circuits. You can now see updates from other collaborators instantaneously, with colored visual cues indicating who has changed the diagram and where that change occurred. Try the new draw.io collaborative beta at &lt;a href="https://rt.draw.io/"&gt;rt.draw.io&lt;/a&gt; and watch the video below.&lt;br /&gt;
&lt;br /&gt;
&lt;iframe width="480" height="270" src="http://www.youtube.com/embed/oQrSpyUhDYw" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;h2&gt;
Learn more about the Drive Realtime API&lt;/h2&gt;
We also built a &lt;a href="https://realtime-cube.appspot.com/"&gt;collaborative colored cube puzzle&lt;/a&gt;&amp;nbsp;so you can have some fun while trying out the Drive Realtime API and a &lt;a href="https://realtimeplayground.appspot.com/"&gt;Drive Realtime API Playground&lt;/a&gt; to take you through the API step-by-step. Both apps are open source so check out our &lt;a href="https://github.com/googledrive"&gt;Github repos&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Have a look at the &lt;a href="https://developers.google.com/drive/realtime"&gt;Google Drive Realtime API technical documentation&lt;/a&gt; and start making your app realtime-enabled!&lt;br /&gt;
&lt;br /&gt;
&lt;table cellpadding="5" cellspacing="0"&gt;&lt;tbody&gt;
&lt;tr style="background-color: #f2f2f2;"&gt;&lt;td&gt;&lt;img src="http://1.bp.blogspot.com/-KODZ9c9OQEI/UUNg__y8dBI/AAAAAAAAA_g/S2dK68Qk8qA/s100/image04.jpg" style="border: none;" /&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;span class="largefont"&gt;Brian Cairns&lt;/span&gt; &amp;nbsp;   &lt;a class="alt" href="https://plus.google.com/111768581593488186219/posts" rel="me" target="_blank"&gt;profile&lt;/a&gt; 
&lt;br /&gt;
&lt;div class="bio"&gt;
&lt;br /&gt;
Brian joined the Google Drive team in 2011 and lives in Boulder, Colorado. He is currently the lead software engineer for the Drive Realtime API. 
&lt;/div&gt;
&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;img src="http://feeds.feedburner.com/~r/GoogleAppsDeveloperBlog/~4/m0wc2KJN_BY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://googleappsdeveloper.blogspot.com/feeds/317334457163160189/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1377183911445147227&amp;postID=317334457163160189&amp;isPopup=true" title="7 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/317334457163160189?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/317334457163160189?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GoogleAppsDeveloperBlog/~3/m0wc2KJN_BY/build-collaborative-apps-with-google.html" title="Build collaborative apps with Google Drive Realtime API" /><author><name>Google Apps Developer Blog Editor</name><uri>http://www.blogger.com/profile/07808045840831274565</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-qFtKuBsMOfI/UUNg_v0AJnI/AAAAAAAAA_U/i2G61boQmSA/s72-c/image01.png" height="72" width="72" /><thr:total>7</thr:total><feedburner:origLink>http://googleappsdeveloper.blogspot.com/2013/03/build-collaborative-apps-with-google.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEYCSX89cCp7ImA9WhBQEkw.&quot;"><id>tag:blogger.com,1999:blog-1377183911445147227.post-3118251155591770735</id><published>2013-03-13T16:08:00.000-07:00</published><updated>2013-03-13T16:09:28.168-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-03-13T16:09:28.168-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Apps Script" /><title>Retiring a Few Apps Script Components</title><content type="html">&lt;p&gt;Right now, Apps Script developers have three competing ways to create user interfaces: &lt;a href="https://developers.google.com/apps-script/uiapp"&gt;Ui Service&lt;/a&gt;, a visual tool for Ui Service called &lt;a href="https://developers.google.com/apps-script/gui_builder"&gt;GUI Builder&lt;/a&gt;, and &lt;a href="https://developers.google.com/apps-script/html_service"&gt;Html Service&lt;/a&gt;, which we launched at Google I/O in 2012. We designed Html Service specifically to help developers build complex applications by letting them work with familiar libraries like jQuery and jQuery UI.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://googleblog.blogspot.com/2013/03/a-second-spring-of-cleaning.html"&gt;Today, we are deprecating&lt;/a&gt; GUI Builder and five UiApp widgets — but not Ui Service itself. This will help us further focus our development efforts on Html Service.

&lt;p&gt;The GUI Builder will continue to be available &lt;a href="https://developers.google.com/apps-script/sunset"&gt;until September 9, 2013&lt;/a&gt;. After that point, you will not be able to create or manage GUI Builder components, although existing components will still function. The five deprecated UiApp widgets are &lt;a href="https://developers.google.com/apps-script/class_hyperlink"&gt;Hyperlink&lt;/a&gt;, &lt;a href="https://developers.google.com/apps-script/class_inlinehyperlink"&gt;InlineHyperlink&lt;/a&gt;, &lt;a href="https://developers.google.com/apps-script/class_layoutpanel"&gt;LayoutPanel&lt;/a&gt;, &lt;a href="https://developers.google.com/apps-script/class_richtextarea"&gt;RichTextArea&lt;/a&gt;, and &lt;a href="https://developers.google.com/apps-script/class_suggestbox"&gt;SuggestBox&lt;/a&gt;. These widgets will be also available until September 9, 2013, at which point they will cease to function.&lt;/p&gt;

&lt;p&gt;To plan for the future, we recommend that you migrate your user interfaces to Html Service, which will offer the best combination of features and support in the long term.&lt;/p&gt;

&lt;p&gt;Meanwhile, we have a few awesome new features planned for 2013. Although we’re not quite ready to announce those features, I dropped a few hints when &lt;a href="https://plus.google.com/117678608428606781684/posts"&gt;Arun Nagarajan&lt;/a&gt; interviewed me for a State of the Script episode on &lt;a href="https://developers.google.com/live/drive/"&gt;Google Developers Live&lt;/a&gt; last month. Give it a watch, and I’m sure you’ll be as excited about the future of Apps Script as we are.&lt;/p&gt;
&lt;p/&gt;
&lt;iframe width="520" height="390" src="http://www.youtube.com/embed/b0GkGlG6kQY" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;
&lt;p/&gt;
&lt;table cellpadding="5" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr style="background-color: #f2f2f2;"&gt;&lt;td&gt;&lt;img class="profile" src="http://1.bp.blogspot.com/-LavP1vCutPo/T-q1FW-Lo2I/AAAAAAAAAZg/GavUBu7obv8/s320/saurabh_photo.png" width=64 height=90/&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;span class="largefont"&gt;Saurabh Gupta&lt;/span&gt; &amp;nbsp;   &lt;a class="alt" href="https://profiles.google.com/sg1705" rel="me" target="_blank"&gt;profile&lt;/a&gt; | &lt;a class="alt" href="http://twitter.com/gluemesh" rel="me" target="_blank"&gt;twitter&lt;/a&gt; | &lt;a class="alt" href="http://www.gluemesh.com/" rel="me" target="_blank"&gt;blog&lt;/a&gt;&lt;br /&gt;&lt;div class="bio"&gt;&lt;br /&gt;As the product manager for Google Apps Script, Saurabh is responsible for Apps Script’s overall vision and direction.&lt;/div&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;img src="http://feeds.feedburner.com/~r/GoogleAppsDeveloperBlog/~4/rkVrZR4gNsE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://googleappsdeveloper.blogspot.com/feeds/3118251155591770735/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1377183911445147227&amp;postID=3118251155591770735&amp;isPopup=true" title="18 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/3118251155591770735?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/3118251155591770735?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GoogleAppsDeveloperBlog/~3/rkVrZR4gNsE/retiring-a-few-apps-script-components.html" title="Retiring a Few Apps Script Components" /><author><name>Google Apps Developer Blog Editor</name><uri>http://www.blogger.com/profile/07808045840831274565</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://img.youtube.com/vi/b0GkGlG6kQY/default.jpg" height="72" width="72" /><thr:total>18</thr:total><feedburner:origLink>http://googleappsdeveloper.blogspot.com/2013/03/retiring-a-few-apps-script-components.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE4NR3szfyp7ImA9WhBQEU8.&quot;"><id>tag:blogger.com,1999:blog-1377183911445147227.post-8600707412904195572</id><published>2013-03-12T14:16:00.001-07:00</published><updated>2013-03-12T14:16:36.587-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-03-12T14:16:36.587-07:00</app:edited><title>Even more Image Metadata for the Google Drive SDK</title><content type="html">&lt;p&gt;Lots of photographers, both professionals and amateurs, have started using Google Drive to store their photos online. We recently launched new features such as a way to quickly preview files and today I wanted to share more details about the image media metadata capabilities of the Drive SDK.&lt;/p&gt;

&lt;p&gt;All digital cameras add some &lt;a href="http://en.wikipedia.org/wiki/Exchangeable_image_file_format"&gt;Exif&lt;/a&gt; information to the photos they take, and we exposed an initial set of Exif fields via the Google Drive API &lt;a href="http://googleappsdeveloper.blogspot.com/2012/10/new-image-metadata-for-google-drive-sdk.html"&gt;at the end of 2012&lt;/a&gt;. That set of metadata has now been expanded to include 9 new fields, such as the sensor type or the metering mode.&lt;/p&gt;

&lt;p&gt;For instance, take a look at this recently taken photo:&lt;/p&gt;
&lt;p/&gt;

&lt;div style="text-align: center;"&gt;
&lt;img border="0" src="http://3.bp.blogspot.com/-vShmy8aY4nY/UT-aRY1zbmI/AAAAAAAAA_E/wIpLuOgk3lA/s480/image00.jpg" /&gt;
&lt;p&gt;Photo credit: Claudio Cherubino&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;What follows is the image media metadata as returned by the Drive API (in bold the new fields):&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
"imageMediaMetadata": {
  "width": 2048,
  "height": 1536,
  "rotation": 0,
  "date": "2013:02:18 12:51:51",
  "cameraMake": "Panasonic",
  "cameraModel": "DMC-GF2",
  "exposureTime": 0.0025,
  "aperture": 7.1,
  "flashUsed": false,
  "focalLength": 14.0,
  "isoSpeed": 100,
  &lt;b&gt;"meteringMode": "Pattern",
  "sensor": "One-chip color area",
  "exposureMode": "Auto",
  "colorSpace": "sRGB",
  "whiteBalance": "Auto",
  "exposureBias": 0.0,
  "maxApertureValue": 3.6289062&lt;/b&gt;
 }
&lt;/pre&gt;

&lt;p&gt;You might have noticed that a number of fields have been added to the response while others (“subjectDistance” and “lens”) were not returned. This is expected as the camera doesn’t have to populate all Exif fields and in that case the corresponding properties will simply not be included in the API response.&lt;/p&gt;

&lt;p&gt;For more information and to check the description of all metadata fields returned by the API, check the &lt;a href="https://developers.google.com/drive/v2/reference/files"&gt;Files resource Reference Guide&lt;/a&gt;. If you have technical questions, please post them on Stack Overflow, my team monitors the &lt;a href="http://stackoverflow.com/questions/tagged/google-drive-sdk"&gt;google-drive-sdk&lt;/a&gt; tag and is happy to help.&lt;/p&gt;



&lt;p&gt;&lt;table cellpadding="5" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr style="background-color: #f2f2f2;"&gt;&lt;td&gt;&lt;img class="profile" src="http://4.bp.blogspot.com/-dlrMe7xZ-to/TlaWF9TImaI/AAAAAAAAAM4/ih9HtRk8AMY/s1600/Google%2BChromeScreenSnapz248.png" /&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;span class="largefont"&gt;Claudio Cherubino&lt;/span&gt; &amp;nbsp;   &lt;a class="alt" href="https://profiles.google.com/claudiocherubino" rel="me" target="_blank"&gt;profile&lt;/a&gt; | &lt;a class="alt" href="http://twitter.com/#ccherubino" rel="me" target="_blank"&gt;twitter&lt;/a&gt; | &lt;a class="alt" href="http://www.claudiocherubino.it/" rel="me" target="_blank"&gt;blog&lt;/a&gt;
&lt;br /&gt;&lt;div class="bio"&gt;
&lt;br /&gt;Claudio is an engineer in the Google Drive Developer Relations team. Prior to Google, he worked as software developer, technology evangelist, community manager, consultant, technical translator and has contributed to many open-source projects. His current interests include Google APIs, new technologies and coffee.&lt;/div&gt;
&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;

&lt;img src="http://feeds.feedburner.com/~r/GoogleAppsDeveloperBlog/~4/cFln9OV5tTM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://googleappsdeveloper.blogspot.com/feeds/8600707412904195572/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1377183911445147227&amp;postID=8600707412904195572&amp;isPopup=true" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/8600707412904195572?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/8600707412904195572?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GoogleAppsDeveloperBlog/~3/cFln9OV5tTM/even-more-image-metadata-for-google.html" title="Even more Image Metadata for the Google Drive SDK" /><author><name>Google Apps Developer Blog Editor</name><uri>http://www.blogger.com/profile/07808045840831274565</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-vShmy8aY4nY/UT-aRY1zbmI/AAAAAAAAA_E/wIpLuOgk3lA/s72-c/image00.jpg" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://googleappsdeveloper.blogspot.com/2013/03/even-more-image-metadata-for-google.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkYGRng7eSp7ImA9WhBRFUQ.&quot;"><id>tag:blogger.com,1999:blog-1377183911445147227.post-408079095681041160</id><published>2013-03-06T09:15:00.000-08:00</published><updated>2013-03-06T09:15:27.601-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-03-06T09:15:27.601-08:00</app:edited><title>Google Drive Hackathon in Mountain View, CA</title><content type="html">&lt;p&gt;Hey Silicon Valley developers,&lt;/p&gt;

&lt;p&gt;We are organizing a Google Drive hackathon next week. If you’d like to learn more about the &lt;a href="https://developers.google.com/drive/"&gt;Google Drive SDK&lt;/a&gt;, meet with Google Drive engineers and have fun developing your first Google Drive application or integrating your existing application, join us.&lt;/p&gt;

&lt;p&gt;The event will take place at the &lt;a href="https://maps.google.com/maps/place?ftid=0x808fba02743ea537:0xcaf84b7dcaf542dc"&gt;Googleplex in Mountain View, CA&lt;/a&gt;. We’ll start with an introduction to the Google Drive SDK at 4:00 p.m. on Wednesday March 13th 2013 and the hackathon will run through the next day at 3:00 p.m. See the &lt;a href="https://plus.google.com/events/c3qjdcm0sk4os4aroqga8r48i14"&gt;detailed agenda&lt;/a&gt; of this event, don’t forget to &lt;a href="https://docs.google.com/a/google.com/forms/d/1zm3ROB13j6zLsRziwOEkzvN9pB8AhKxw2KqcSU6tAn0/viewform"&gt;RSVP&lt;/a&gt; and tell your friends about it.&lt;/p&gt;

&lt;p&gt;Also there will be some exciting Google prizes for the best apps.&lt;/p&gt;

&lt;p&gt;See you there!&lt;/p&gt;

&lt;p&gt;
&lt;table cellpadding="5" cellspacing="0"&gt;&lt;tbody&gt;
&lt;tr style="background-color: #f2f2f2;"&gt;&lt;td&gt;&lt;img class="profile" src="http://sites.google.com/site/developeradvocates/image/nicolas_garnier.png" /&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;span class="largefont"&gt;Nicolas Garnier&lt;/span&gt;   &lt;a class="alt" href="https://plus.google.com/108635752367054807758?rel=author" target="_blank"&gt;Google+&lt;/a&gt; | &lt;a class="alt" href="http://twitter.com/nivco" rel="me" target="_blank"&gt;Twitter&lt;/a&gt;&lt;br /&gt;
&lt;div class="bio"&gt;
&lt;br /&gt;
Nicolas Garnier joined Google’s Developer Relations in 2008 and lives in Zurich. He is a Developer Advocate for Google Drive and Google Apps. Nicolas is also the lead engineer for the &lt;a href="https://developers.google.com/oauthplayground/" target="_blank"&gt;OAuth 2.0 Playground&lt;/a&gt;.&lt;/div&gt;
&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GoogleAppsDeveloperBlog/~4/ca47B86qX8U" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://googleappsdeveloper.blogspot.com/feeds/408079095681041160/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1377183911445147227&amp;postID=408079095681041160&amp;isPopup=true" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/408079095681041160?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/408079095681041160?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GoogleAppsDeveloperBlog/~3/ca47B86qX8U/google-drive-hackathon-in-mountain-view.html" title="Google Drive Hackathon in Mountain View, CA" /><author><name>Google Apps Developer Blog Editor</name><uri>http://www.blogger.com/profile/07808045840831274565</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://googleappsdeveloper.blogspot.com/2013/03/google-drive-hackathon-in-mountain-view.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkIFQHc5fyp7ImA9WhBREE0.&quot;"><id>tag:blogger.com,1999:blog-1377183911445147227.post-3668248714657348688</id><published>2013-02-27T14:35:00.000-08:00</published><updated>2013-02-27T14:35:11.927-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-27T14:35:11.927-08:00</app:edited><title>How to make files searchable in Google Drive</title><content type="html">&lt;p&gt;When a file of a common type is uploaded to Google Drive, it is automatically indexed so users can easily search for it in their Drive files. Google Drive also tries to recognize objects and landmarks in images uploaded to Drive.&lt;/p&gt;

&lt;p&gt;For instance, if a user uploaded a list of customers as an HTML, XML, PDF or text file he could easily find it later by searching for one of its customer’s name that is written inside the file. Users could also upload a picture of their favorite green robot, then search for “Android” and Google Drive would find it in their Drive:&lt;/p&gt;

&lt;p/&gt;

&lt;div style="text-align: center;"&gt;
&lt;img border="0" src="http://2.bp.blogspot.com/-sVN5JRpZhhA/US6Hff2mU0I/AAAAAAAAA-M/vkjUxOBYo94/s480/image00.png" /&gt;
&lt;div&gt;&lt;i&gt;Searching for “Android” finds images containing the Android logo.&lt;/i&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Metadata such as the file’s title and description are always indexed so users can always find a file by name. However, Google Drive does not automatically index the content of less common or custom file types. For example if your application uploads or creates files using the custom MIME-type &lt;code&gt;custom/mime.type&lt;/code&gt;, then Drive would not try to read and index the content of these files and your users would not be able to find them by searching for something that’s inside these files.&lt;/p&gt;

&lt;p&gt;To have Google Drive index the content of such files you have to use one of the following two options available when uploading files through the Google Drive API.&lt;/p&gt;

&lt;p/&gt;
&lt;h3&gt;useContentAsIndexableText URL parameter&lt;/h3&gt;
&lt;p/&gt;

&lt;p&gt;We recently added a way for you to indicate that the file you are uploading is using a readable text format. In the case where your file data format is text based — for instance if you are using XML or JSON — you can simply set the &lt;a href="https://developers.google.com/drive/v2/reference/files/insert#useContentAsIndexableText"&gt;&lt;code&gt;useContentAsIndexableText&lt;/code&gt; URL parameter&lt;/a&gt; to true when uploading the file’s content to Drive. When this flag is set Google Drive will try to read the content of the file as text and index it.&lt;/p&gt;

&lt;p/&gt;
&lt;h3&gt;indexableText attribute&lt;/h3&gt;
&lt;p/&gt;

&lt;p&gt;There is a more flexible approach which is to set the &lt;a href="https://developers.google.com/drive/v2/reference/files/insert#indexableText.text"&gt;&lt;code&gt;indexableText&lt;/code&gt; attribute&lt;/a&gt; on the File Metadata. You can set the value of the &lt;code&gt;indexableText&lt;/code&gt; attribute which is a hidden — write-only — attribute that we will index for search. This is very useful if you are using &lt;a href="https://developers.google.com/drive/integrate-create#create_a_shortcut_to_a_file"&gt;a shortcut file&lt;/a&gt; — in which case there is no content uploaded to Google Drive — or if you are using a non-text or binary file format which Google Drive won’t be able to read.&lt;/p&gt;

&lt;p&gt;Have a look at our &lt;a href="https://developers.google.com/drive/v2/reference/files/insert"&gt;Google Drive API references&lt;/a&gt; or watch our latest &lt;a href="https://developers.google.com/live/shows/31119462-5001/"&gt;Google Developer Live video&lt;/a&gt; about the topic to learn more.&lt;/p&gt;

&lt;p/&gt;
&lt;iframe width="560" height="315" src="http://www.youtube.com/embed/1hnungYNAhQ" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;
&lt;p/&gt;

&lt;p&gt;
&lt;table cellpadding="5" cellspacing="0"&gt;&lt;tbody&gt;
&lt;tr style="background-color: #f2f2f2;"&gt;&lt;td&gt;&lt;img class="profile" src="http://sites.google.com/site/developeradvocates/image/nicolas_garnier.png" /&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;span class="largefont"&gt;Nicolas Garnier&lt;/span&gt;   &lt;a class="alt" href="https://plus.google.com/108635752367054807758?rel=author" target="_blank"&gt;Google+&lt;/a&gt; | &lt;a class="alt" href="http://twitter.com/nivco" rel="me" target="_blank"&gt;Twitter&lt;/a&gt;&lt;br /&gt;
&lt;div class="bio"&gt;
&lt;br /&gt;
Nicolas Garnier joined Google’s Developer Relations in 2008 and lives in Zurich. He is a Developer Advocate for Google Drive and Google Apps. Nicolas is also the lead engineer for the &lt;a href="https://developers.google.com/oauthplayground/" target="_blank"&gt;OAuth 2.0 Playground&lt;/a&gt;.&lt;/div&gt;
&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GoogleAppsDeveloperBlog/~4/uK2nmyoI9yE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://googleappsdeveloper.blogspot.com/feeds/3668248714657348688/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1377183911445147227&amp;postID=3668248714657348688&amp;isPopup=true" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/3668248714657348688?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/3668248714657348688?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GoogleAppsDeveloperBlog/~3/uK2nmyoI9yE/how-to-make-files-searchable-in-google.html" title="How to make files searchable in Google Drive" /><author><name>Google Apps Developer Blog Editor</name><uri>http://www.blogger.com/profile/07808045840831274565</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-sVN5JRpZhhA/US6Hff2mU0I/AAAAAAAAA-M/vkjUxOBYo94/s72-c/image00.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://googleappsdeveloper.blogspot.com/2013/02/how-to-make-files-searchable-in-google.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUQGQXY_cSp7ImA9WhBSGU0.&quot;"><id>tag:blogger.com,1999:blog-1377183911445147227.post-8795918823091130916</id><published>2013-02-26T11:35:00.000-08:00</published><updated>2013-02-26T11:35:20.849-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-26T11:35:20.849-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Google+" /><category scheme="http://www.blogger.com/atom/ns#" term="Android" /><category scheme="http://www.blogger.com/atom/ns#" term="Drive SDK" /><title>Introducing Google+ Sign-In for your Drive Apps</title><content type="html">&lt;p&gt;What does the &lt;a href="http://googledevelopers.blogspot.com/2013/02/introducing-google-sign-in-simple-and.html"&gt;new&lt;/a&gt; &lt;a href="https://developers.google.com/+/features/sign-in"&gt;Google+ Sign-In&lt;/a&gt; mean for your Drive app, and why should you use it?&lt;/p&gt;
&lt;p/&gt;
&lt;div style="text-align: center;"&gt;
&lt;img border="0" style="border: none;" src="http://3.bp.blogspot.com/-F-43eNmIWUs/US0KCMfGm7I/AAAAAAAAA9E/TqfTFEK4Lg0/s480/image00.jpg"&gt;
&lt;/div&gt;

&lt;h3&gt;Google+ Sign-In is not just about Google+&lt;/h3&gt;
&lt;p/&gt;
&lt;p&gt;All APIs can be authorized using the “Sign in with Google” button, including the Drive API. To authorize additional scopes, just pass them in the markup for the “Sign in with Google” button like we’ve done in this example.&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
&amp;lt;span class="g-signin"
      data-scope="https://www.googleapis.com/auth/drive.file"&amp;gt;
&lt;/pre&gt;

&lt;h3&gt;Ready-made button to allow users to connect with Google&lt;/h3&gt;
&lt;p/&gt;
&lt;p&gt;The “Sign in with Google” button can cater to whatever kind of application you create: web, client, or mobile. Now you can choose the authorization flow you like and get a token using the OAuth 2.0 client-side flow or server flow. There are loads of features, and the button is &lt;a href="https://developers.google.com/+/web/signin/#sign-in_button_attributes"&gt;highly customizable&lt;/a&gt;.&lt;/p&gt;
&lt;p/&gt;
&lt;div style="text-align: center;"&gt;
&lt;img border="0" style="border: none; height: 40px;" src="http://1.bp.blogspot.com/-DNSJX8Bb9PU/US0KCF_CIII/AAAAAAAAA9A/PefTt0rXFaU/s180/image02.png" /&gt;
&lt;img border="0" style="border: none; height: 40px;" src="http://4.bp.blogspot.com/-gE0zZ0VNNtM/US0KCd6WQFI/AAAAAAAAA9I/8MJTc3qy6dU/s180/image03.png" /&gt;
&lt;img border="0" style="border: none; height: 40px;"  src="http://4.bp.blogspot.com/-Cc6s5DhfBfA/US0KCP-yKxI/AAAAAAAAA9M/R8zZYVXSS4I/s180/image01.png" /&gt;
&lt;/div&gt;

&lt;p&gt;I’ve saved my favorite feature until the end: when the user authorizes an application on the web, &lt;i&gt;the mobile version of the app &lt;a href="https://developers.google.com/+/features/play-installs"&gt;can be installed&lt;/a&gt; over the air onto their mobile device&lt;/i&gt;. Just add your Android package name when you create the button like in this second example, and your app will be automagically installed.&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
&amp;lt;span class="g-signin"
      data-apppackagename="org.aliafshar.android.driveapp"&amp;gt;
&lt;/pre&gt;

&lt;p&gt;I know many of your Drive apps have mobile and web components, so this should be really useful for you. This helps you provide your users with a beautiful and seamless experience on all of their devices.&lt;/p&gt;

&lt;p&gt;All-in-all, we think you’ll find these features useful and recommend that you use the Google+ Sign-In as the preferred way to authorize a user with the Google Drive API from inside a user interface. Check out how to &lt;a href="https://developers.google.com/+/features/sign-in"&gt;get started&lt;/a&gt; with Google+ Sign-In in the language of your choice.&lt;/p&gt;


&lt;p&gt;
&lt;table cellpadding="5" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr style="background-color: #f2f2f2;"&gt;&lt;td&gt;&lt;img class="profile" src="https://sites.google.com/site/developeradvocates/image/ali_afshar.png" /&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;span class="largefont"&gt;Ali Afshar&lt;/span&gt;   &lt;a class="alt" href="https://plus.google.com/118327176775959145936/" rel="me" target="_blank"&gt;profile&lt;/a&gt; | &lt;a class="alt" href="http://twitter.com/#!/aliafshar"&gt;twitter&lt;/a&gt;
&lt;br /&gt;&lt;div class="bio"&gt;
&lt;br /&gt;Tech Lead, Google Drive Developer Relations. As an eternal open source advocate, he contributes to a number of open source applications, and is the author of the PIDA Python IDE. Once an intensive care physician, he has a special interest in all aspects of technology for healthcare&lt;/div&gt;
&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/GoogleAppsDeveloperBlog/~4/xL-7u9GtVk8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://googleappsdeveloper.blogspot.com/feeds/8795918823091130916/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1377183911445147227&amp;postID=8795918823091130916&amp;isPopup=true" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/8795918823091130916?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/8795918823091130916?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GoogleAppsDeveloperBlog/~3/xL-7u9GtVk8/introducing-google-sign-in-for-your.html" title="Introducing Google+ Sign-In for your Drive Apps" /><author><name>Google Apps Developer Blog Editor</name><uri>http://www.blogger.com/profile/07808045840831274565</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-F-43eNmIWUs/US0KCMfGm7I/AAAAAAAAA9E/TqfTFEK4Lg0/s72-c/image00.jpg" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://googleappsdeveloper.blogspot.com/2013/02/introducing-google-sign-in-for-your.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUIGQn05cSp7ImA9WhBTF0o.&quot;"><id>tag:blogger.com,1999:blog-1377183911445147227.post-6493589190194140883</id><published>2013-02-13T09:45:00.000-08:00</published><updated>2013-02-13T09:45:23.329-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-13T09:45:23.329-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Apps Script" /><category scheme="http://www.blogger.com/atom/ns#" term="Guest Post" /><title>Crowdsourcing Localization with Google Apps Script</title><content type="html">&lt;p&gt;&lt;i&gt;Editor’s Note: Guest author John Gale is a Solutions Developer at &lt;a href="http://www.appogee.co.uk/"&gt;Appogee&lt;/a&gt;, a Google Cloud Service Partner. — Arun Nagarajan&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;Ever since we launched &lt;a href="http://www.appogeeleave.com/"&gt;Appogee Leave&lt;/a&gt; — the first tool in the &lt;a href="https://www.google.com/enterprise/marketplace/viewListing?productListingId=5871+5337419499322135726"&gt;Google Apps Marketplace&lt;/a&gt; for tracking employees’ absences and time off — customers have been asking, “Can you support my native language?”&lt;/p&gt;

&lt;p&gt;Our partners offered to help crowdsource the translation, but it was a challenge to know where to begin. We started by identifying a few needs:&lt;/p&gt;
&lt;ul&gt;
&lt;li /&gt;Users must be able to provide new translations
&lt;li /&gt;Users must be able to flag bad translations and recommend changes
&lt;li /&gt;Developers must be able to integrate completed translations
&lt;li /&gt;Customer service must be able to keep users informed of progress
&lt;/ul&gt;

&lt;p&gt;With just a couple days’ effort in Google Apps Script, we created a &lt;a href="http://www.appogeeleave.com/translate"&gt;complete application for crowd-sourced localization&lt;/a&gt; that handles each of those requirements. You can get a glimpse of the system in the screenshot below.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://2.bp.blogspot.com/-C6MABiPmNQM/URmmqdJtGHI/AAAAAAAAA8M/_jdRLhC9aHI/s1600/appogee1.png" imageanchor="1" style=""&gt;&lt;img border="0" width="520" src="http://2.bp.blogspot.com/-C6MABiPmNQM/URmmqdJtGHI/AAAAAAAAA8M/_jdRLhC9aHI/s520/appogee1.png" /&gt;&lt;/a&gt;

&lt;i&gt;Source: Appogee&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;Let’s take a look at a few specific Apps Script tricks we used to make the whole thing work.&lt;/p&gt;

&lt;br /&gt;

&lt;h3&gt;Avoid Collisions with Lock Service&lt;/h3&gt;

&lt;p&gt;Like many Apps Script users, we store almost all of the data for our translation system in Google Sheets, including both the list of English terms we want to translate and users’ translations.&lt;/p&gt;

&lt;p&gt;During testing, we found that if two users submitted translations at the same time, the spreadsheet wrote both sets of changes to the same place, causing us to lose one user’s updates. To solve this, we use Apps Script’s semaphore-based &lt;a href="https://developers.google.com/apps-script/service_lock"&gt;Lock Service&lt;/a&gt;. In the code below, a public lock ensures that a user has temporary exclusive use of the spreadsheet so that their correction is added even if another user also submits a correction.&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
function submit(e){
  /*  get the fields from the UI callback  */
  var incorrect = e.parameter.foreignWordIncorrectTxt;
  var correct = e.parameter.foreignWordCorrectTxt;
  var reason = e.parameter.reasonTxt;
  var lang = e.parameter.hiddenLang;

  /*  validate the input; return the user a message if invalid  */
 
  /*  open the spreadsheet  */
  var active_user_email = UserProperties.getProperty('user_email') || "";
  var master_spreadsheet = SpreadsheetApp.openById(MASTER_SPREADSHEET_KEY);
  var correction_sheet = master_spreadsheet.getSheetByName('Corrections');
    
  /*  get a lock and update the spreadsheet  */
  var lock = LockService.getPublicLock();
  lock.waitLock(30000);    
  correction_sheet.appendRow([
      lang, incorrect, correct, reason, active_user_email
    ]);
  SpreadsheetApp.flush();
  lock.releaseLock();

  /*  reset the UI  */
  return reset();
}
&lt;/pre&gt;

&lt;p&gt;You’ll note that this code opens the spreadsheet before obtaining a lock. At this point, we are only reading, not writing, and thus do not yet require a lock. We then tell Apps Script we are prepared to wait up to 30 seconds for our turn to lock the worksheet. On the rare occasion that a lock is not available within 30 seconds (usually because somebody else has an exclusive lock), the code throws an exception and stops execution.&lt;/p&gt;

&lt;p&gt;Once we have acquired the lock, we quickly write the correction to the spreadsheet — including a call to &lt;a href="https://developers.google.com/apps-script/class_spreadsheetapp#flush"&gt;&lt;code class="prettyprint"&gt;SpreadsheetApp.flush()&lt;/code&gt;&lt;/a&gt; to ensure the data is written immediately — and release the lock.&lt;/p&gt;

&lt;br /&gt;

&lt;h3&gt;Save Time with Cache Service&lt;/h3&gt;

&lt;p&gt;Because the translations are stored in a spreadsheet along with information about who provided them, it’s easy to recognize our top contributors through a leaderboard. The leaderboard data is a good candidate for caching because it’s shown to a large number of people, but only changes when we receive new updates from top-ranking users.&lt;/p&gt;

&lt;p&gt;Like the Lock Service described earlier, the &lt;a href="https://developers.google.com/apps-script/service_cache"&gt;Cache Service&lt;/a&gt; provides both public and private variants. The public cache is useful for storing data that should be available to all users, such as the leaderboard. The private cache is more appropriate for storing information about a user, such as the translations they have submitted so far.&lt;/p&gt;

&lt;p&gt;Since the Apps Script cache can only store strings, complex objects must first be converted. Lucky for us, Apps Script provides JSON utilities that make this conversion easy, as shown in this example:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
function getBoardData(){
  var cache = CacheService.getPublicCache();
  var leaderboard_data = cache.get('leaderboard_data');
  if (leaderboard_data == null) {
    leaderboard_data = getTopTen();
    cache.put('leaderboard_data',
              Utilities.jsonStringify(leaderboard_data),
              3600);
  } else {
    leaderboard_data = Utilities.jsonParse(leaderboard_data);
  }
  return leaderboard_data;
}
&lt;/pre&gt;

&lt;p&gt;Our hope is that the leaderboard will encourage users to provide more translations by introducing some friendly competition.&lt;/p&gt;

&lt;p&gt;Thanks to Google Apps Script and the techniques shown above, we built a powerful crowdsourcing translation system without unnecessary complexity or development effort. If you’d like to help translate Appogee Leave, &lt;a href="http://www.appogeeleave.com/translate/"&gt;we’d love to have your contribution&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://3.bp.blogspot.com/-ST9ZZVxj0h4/URmmr2n0pXI/AAAAAAAAA8U/31dpUaWyuSs/s1600/appogee2.png" imageanchor="1" style=""&gt;&lt;img border="0" width="520" src="http://3.bp.blogspot.com/-ST9ZZVxj0h4/URmmr2n0pXI/AAAAAAAAA8U/31dpUaWyuSs/s520/appogee2.png" /&gt;&lt;/a&gt;

&lt;i&gt;Source: Appogee&lt;/i&gt;&lt;/p&gt;

&lt;table cellpadding="5" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr style="background-color: #f2f2f2;"&gt;&lt;td&gt;&lt;img class="profile" src="http://1.bp.blogspot.com/-xNh3eUqGchI/URmmsEtJDxI/AAAAAAAAA8g/sjd_i1SjIE4/s400/appogee3.jpg" /&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;span class="largefont"&gt;John Gale&lt;/span&gt; &amp;nbsp;   &lt;a class="alt" href="https://plus.google.com/110621995784033485929" rel="me" target="_blank"&gt;profile&lt;/a&gt; | &lt;a class="alt" href="https://twitter.com/AppogeeLeave" rel="me" target="_blank"&gt;twitter&lt;/a&gt;&lt;br /&gt;&lt;div class="bio"&gt;&lt;br /&gt;John Gale is a Solutions Developer at &lt;a href="http://www.appogee.co.uk/"&gt;Appogee&lt;/a&gt;, a Google Cloud Service Partner. John develops software that helps customers make the most of the Google Cloud platform. He has worked on a range of cloud-based applications including Google Apps Marketplace applications, client projects involving Lotus Notes application migration, and mobile data-capture applications.
&lt;/div&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;img src="http://feeds.feedburner.com/~r/GoogleAppsDeveloperBlog/~4/gkOhIs9lDl8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://googleappsdeveloper.blogspot.com/feeds/6493589190194140883/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1377183911445147227&amp;postID=6493589190194140883&amp;isPopup=true" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/6493589190194140883?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/6493589190194140883?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GoogleAppsDeveloperBlog/~3/gkOhIs9lDl8/crowdsourcing-localization-with-google.html" title="Crowdsourcing Localization with Google Apps Script" /><author><name>Google Apps Developer Blog Editor</name><uri>http://www.blogger.com/profile/07808045840831274565</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-C6MABiPmNQM/URmmqdJtGHI/AAAAAAAAA8M/_jdRLhC9aHI/s72-c/appogee1.png" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://googleappsdeveloper.blogspot.com/2013/02/crowdsourcing-localization-with-google.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUIMQns4cSp7ImA9WhNaEU4.&quot;"><id>tag:blogger.com,1999:blog-1377183911445147227.post-4693081901947818873</id><published>2013-01-25T10:13:00.000-08:00</published><updated>2013-01-25T10:13:03.539-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-25T10:13:03.539-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Apps Script" /><title>Apps Script Rewind</title><content type="html">&lt;p&gt;Sometimes you just want to sit uninterrupted at your keyboard, bashing out a clever Apps Script to automate your life and your work … but sometimes you want to see how Google experts approach the tough problems. Sometimes you want to draw on other Apps Scripters for inspiration or help.&lt;/p&gt;

&lt;p&gt;That’s why the Apps Script team — and many other developer-focused teams at Google — record &lt;a href="https://developers.google.com/live/"&gt;Google Developers Live&lt;/a&gt; episodes in which we highlight a specific topic and drill down to discuss it in detail.&lt;/p&gt;

&lt;p&gt;We also hold regular livestreamed office hours via Google+ Hangouts, which we &lt;a href="http://www.youtube.com/playlist?list=PL68F511F6E3C122EB"&gt;post on YouTube afterwards&lt;/a&gt;. In these office hours, we discuss recent releases and give in-depth tutorials on topics interesting to Apps Script users.&lt;/p&gt;

&lt;p&gt;Now that the 2013’s GDLs and office hours are underway, let’s recap six topics we discussed in GDL segments over the last few months.&lt;/p&gt;
&lt;br/&gt;
&lt;h3&gt;Apps Script services&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://developers.google.com/apps-script/understanding_triggers"&gt;Triggers&lt;/a&gt; are an incredibly powerful part of Apps Script that allow developers to run code non-interactively. In this video, I talk about ways to schedule code via the GUI as well as programmatically, and briefly touch on intermediate topics such as common patterns and pitfalls when working with triggers.
&lt;p/&gt;
&lt;iframe width="520" height="390" src="http://www.youtube.com/embed/U9Ej6PCeO6s" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;Charts are a great way to visualize data. In this next video, &lt;a href="https://plus.sandbox.google.com/104332150690924044386/posts"&gt;Kalyan Reddy&lt;/a&gt; starts with a few slides about Apps Script’s &lt;a href="https://developers.google.com/apps-script/service_charts"&gt;Charts Service&lt;/a&gt;, then works his way into code samples for an application that pulls data from the StackOverflow API in order to create an online dashboard that displays contributions from top developers. If you want to follow along, &lt;a href="https://github.com/gkaldevrel/charts-in-apps-script"&gt;Kalyan’s code samples are available on Github&lt;/a&gt;.&lt;/p&gt;
&lt;p/&gt;
&lt;iframe width="520" height="390" src="http://www.youtube.com/embed/3deomYqHKgA" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;
&lt;p/&gt;
&lt;h3&gt;Working with other Google APIs&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://developers.google.com/bigquery/"&gt;BigQuery&lt;/a&gt; is a Google service that allows developers to analyze massive datasets very quickly in the cloud. In this video, &lt;a href="https://plus.sandbox.google.com/106641576811513429422/posts"&gt;Michael Manoochehri&lt;/a&gt; from the BigQuery team joins us to talk about how to use Apps Script to automatically export aggregate BigQuery data into Google Sheets to make it easier to share. This show dovetails nicely with Kalyan’s video about charts (above), in which you’ll learn how to quickly wire up visualizations for the exported data.&lt;/p&gt;
&lt;p/&gt;
&lt;iframe width="520" height="390" src="http://www.youtube.com/embed/aOynZLV4pYA" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;And what developer doesn’t love &lt;a href="http://www.google.com/analytics/"&gt;Google Analytics&lt;/a&gt;? Although Analytics has built-in mechanisms to export data from the UI, it also provides an API for automated data retrieval. Nick Mihailovski from the Google Analytics team joins us to talk about the reasons why people might want to do this, and to demonstrate a toolkit that makes it easy to work with Google Analytics data within Google Sheets.&lt;/p&gt;
&lt;p/&gt;
&lt;iframe width="520" height="390" src="http://www.youtube.com/embed/COpBredC-y0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;
&lt;p/&gt;
&lt;h3&gt;Third-party APIs&lt;/h3&gt;

&lt;p&gt;Many Google Apps users are also &lt;a href="http://www.salesforce.com"&gt;Salesforce&lt;/a&gt; users. In this show, &lt;a href="https://plus.sandbox.google.com/117678608428606781684/posts"&gt;Arun Nagarajan&lt;/a&gt; explains how to integrate Google Apps with Salesforce via Apps Script, and shows off a few code samples that demonstrate moving data between Salesforce and Google Apps in either direction. Make sure to grab a copy of &lt;a href="https://github.com/entaq/GoogleAppsScript/tree/master/Salesforce.com"&gt;Arun’s code samples on Github&lt;/a&gt;.&lt;/p&gt;
&lt;p/&gt;
&lt;iframe width="520" height="390" src="http://www.youtube.com/embed/9SEAmNDtlcA" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;Need to build a robodialer or otherwise automate voice calls? &lt;a href="http://www.twilio.com/"&gt;Twilio&lt;/a&gt; provides an API for doing just that. Arun and &lt;a href="https://plus.sandbox.google.com/103231502413952116096/posts"&gt;Eric Koleda&lt;/a&gt; take us through some of the cool possibilities for integrating Twilio’s API with Google Apps. We had a lot of fun setting up the studio for this one, and it’s one of the most fun to watch. &lt;a href="https://github.com/entaq/GoogleAppsScript/tree/master/Twilio"&gt;Here’s the code on Github&lt;/a&gt;.&lt;/p&gt;
&lt;p/&gt;
&lt;iframe width="520" height="390" src="http://www.youtube.com/embed/j0wjM1Ds3lc" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;Of course, if you want to hear our tricks and tips as soon as possible, you’ll should watch Google Developers Live, well, live — so check out the &lt;a href="https://developers.google.com/live/drive/"&gt;calendar of upcoming episodes for Apps Script and Drive&lt;/a&gt;. If you have any ideas for further segments you’d like to see, leave a suggestion in the comments below! We’d love to hear your feedback.&lt;/p&gt;

&lt;p&gt;Cheers!&lt;/p&gt;

&lt;table cellpadding="5" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr style="background-color: #f2f2f2;"&gt;&lt;td&gt;&lt;img class="profile" src="http://1.bp.blogspot.com/-eOCPsoSGyF0/UDOSp8J0mUI/AAAAAAAAArg/Di-Cs5wwY4M/s1600/ikai_lan.png" /&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;span class="largefont"&gt;Ikai Lan&lt;/span&gt; &amp;nbsp;   &lt;a class="alt" href="https://plus.google.com/107011265359512082824/about" rel="me" target="_blank"&gt;profile&lt;/a&gt;&lt;br /&gt;&lt;div class="bio"&gt;&lt;br /&gt;Ikai is a Developer Programs Engineer working on Google Apps Script but transitioning to the YouTube team. Ikai is an avid technologist, consuming volumes of material about new programming languages, frameworks or services, though more often than not you'll find him advocating pragmatism over dogma in the solutions he proposes. In his free time, he enjoys the great outdoors, winning Chinese language karaoke contests and playing flag football. He resides in New York City, where he watches in anguish as his favorite sports teams from the San Francisco Bay Area implode season after season.&lt;/div&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;img src="http://feeds.feedburner.com/~r/GoogleAppsDeveloperBlog/~4/T-XZUgoauHY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://googleappsdeveloper.blogspot.com/feeds/4693081901947818873/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1377183911445147227&amp;postID=4693081901947818873&amp;isPopup=true" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/4693081901947818873?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/4693081901947818873?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GoogleAppsDeveloperBlog/~3/T-XZUgoauHY/apps-script-rewind.html" title="Apps Script Rewind" /><author><name>Google Apps Developer Blog Editor</name><uri>http://www.blogger.com/profile/07808045840831274565</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://img.youtube.com/vi/U9Ej6PCeO6s/default.jpg" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://googleappsdeveloper.blogspot.com/2013/01/apps-script-rewind.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0cHRn4zeSp7ImA9WhNbGEU.&quot;"><id>tag:blogger.com,1999:blog-1377183911445147227.post-9125714572452189800</id><published>2013-01-22T10:57:00.001-08:00</published><updated>2013-01-22T10:57:17.081-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-22T10:57:17.081-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Drive SDK" /><title>Join the Google Drive SDK Early Access Program</title><content type="html">&lt;p&gt;We're looking for a small set of developers that are committed to building apps for Google Drive to join our &lt;a href="https://developers.google.com/drive/earlyaccess"&gt;Google Drive SDK early access program&lt;/a&gt;. Participants will get early access to upcoming features and the opportunity to shape the direction of the SDK. This is an ongoing program covering multiple aspects of the API, and there are two new features that we're ready to share with developers.&lt;/p&gt;
&lt;p/&gt;
&lt;h3&gt;Google Drive Realtime API&lt;/h3&gt;

&lt;p&gt;Some of you might have already heard of the &lt;a href="http://youtu.be/25HkrDjg6sQ?t=31m58s"&gt;upcoming Google Drive Realtime API&lt;/a&gt; at Google IO 2012. The Google Drive Realtime API will allow you to use the technology that powers the realtime collaboration features of Google products such as Google Docs and Google Sheets in your own application. It will handle all aspects of data transmission, storage, and conflict resolution when multiple users are editing.&lt;/p&gt;

&lt;p&gt;We are looking for trusted testers for what will be a short and intense pre-release phase of the Drive Realtime API. Good candidates will be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;People who are able to start testing and integrating the API very soon ( next week!)&lt;/li&gt;
&lt;li&gt;Web based applications: The API is currently JavaScript-only&lt;/li&gt;
&lt;li&gt;Those who have a good use case for a realtime technology (like web based editors or even web based games...)&lt;/li&gt;
&lt;li&gt;Committed to having their integration ready for the launch of the API&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Google Drive API Push Notifications&lt;/h3&gt;

&lt;p&gt;We also told developers about an &lt;a href="http://youtu.be/25HkrDjg6sQ?t=31m5s"&gt;upcoming Push Notifications&lt;/a&gt; system at Google IO 2012. Push Notifications will allow you to get near-instant notifications when files are modified in Google Drive. In the past you would typically have had to frequently poll the Drive API to check if files have been modified to obtain similar results, Push notifications makes this super efficient.&lt;/p&gt;

&lt;p&gt;Please fill out our &lt;a href="https://docs.google.com/a/google.com/spreadsheet/viewform?formkey=dGZjM25kdnF2dzBLYktaU3BMQ0pIMEE6MA#gid=0"&gt;signup form&lt;/a&gt; to tell us more about your use case and we’ll contact you shortly.&lt;/p&gt;

&lt;p&gt;
&lt;table cellpadding="5" cellspacing="0"&gt;&lt;tbody&gt;
&lt;tr style="background-color: #f2f2f2;"&gt;&lt;td&gt;&lt;img class="profile" src="http://sites.google.com/site/developeradvocates/image/nicolas_garnier.png" /&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;span class="largefont"&gt;Nicolas Garnier&lt;/span&gt;   &lt;a class="alt" href="https://plus.google.com/108635752367054807758?rel=author" target="_blank"&gt;Google+&lt;/a&gt; | &lt;a class="alt" href="http://twitter.com/nivco" rel="me" target="_blank"&gt;Twitter&lt;/a&gt;&lt;br /&gt;
&lt;div class="bio"&gt;
&lt;br /&gt;
Nicolas Garnier joined Google’s Developer Relations in 2008 and lives in Zurich. He is a Developer Advocate for Google Drive and Google Apps. Nicolas is also the lead engineer for the &lt;a href="https://developers.google.com/oauthplayground/" target="_blank"&gt;OAuth 2.0 Playground&lt;/a&gt;.&lt;/div&gt;
&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GoogleAppsDeveloperBlog/~4/dSZf9dTPKvo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://googleappsdeveloper.blogspot.com/feeds/9125714572452189800/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1377183911445147227&amp;postID=9125714572452189800&amp;isPopup=true" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/9125714572452189800?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/9125714572452189800?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GoogleAppsDeveloperBlog/~3/dSZf9dTPKvo/join-google-drive-sdk-early-access.html" title="Join the Google Drive SDK Early Access Program" /><author><name>Google Apps Developer Blog Editor</name><uri>http://www.blogger.com/profile/07808045840831274565</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://googleappsdeveloper.blogspot.com/2013/01/join-google-drive-sdk-early-access.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEINRXw4fip7ImA9WhNUEkk.&quot;"><id>tag:blogger.com,1999:blog-1377183911445147227.post-4506449378303157075</id><published>2013-01-03T11:49:00.000-08:00</published><updated>2013-01-03T11:49:54.236-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-03T11:49:54.236-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Apps Script" /><title>Kicking Apps and Making Names</title><content type="html">&lt;p&gt;Way back in the dawn of time, before I joined Google — OK, fine, two months ago — I was a video-game designer. Occasionally, I had to come up with names for people or places. And I'm no good at naming things.&lt;/p&gt;

&lt;p&gt;So once, instead of manually naming hundreds of towns in a (fictitious) foreign country, I weaseled my way out of creativity by writing a ridiculous set of custom spreadsheet functions. My spreadsheet analyzed a list of real placenames from a similar country, then spit out plausible fake names with the same lexical structure.&lt;/p&gt;

&lt;p&gt;It worked — but I was pushing spreadsheet functions so far that the “code” (if you can call it that) became difficult to maintain. At the same time, the reason I used a spreadsheet in the first place was so I could lean on the analytical power of pivot tables.&lt;/p&gt;

&lt;p&gt;That’s what made Google Apps Script perfect for revamping the project. With Apps Script, I can still use pivot tables, then do the heavy lifting in JavaScript and package everything up as a tidy web app. I call it &lt;a href="https://script.google.com/macros/s/AKfycbxHe-LRN3PQ8lw0cIoXced7s0pCnX73FUbFHd2xow-e7yKmXLE/exec"&gt;Name Generator&lt;/a&gt; … because I’m terrible at naming software, too.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://script.google.com/macros/s/AKfycbxHe-LRN3PQ8lw0cIoXced7s0pCnX73FUbFHd2xow-e7yKmXLE/exec" target="_blank"&gt;&lt;img border="0" width="520" src="http://3.bp.blogspot.com/-NIap28cHzRg/UMpDefAdMUI/AAAAAAAAA4c/IyQVcfongHU/s520/namegen1%2B%25281%2529.png" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, before you say, “There’s no way I’d call my daughter Harliance,” remember that the goal wasn’t to produce real names. The goal was to produce names that were good enough for a video game. Perhaps Harliance is a cyborg woman of negotiable virtue in dystopian future-America? You should probably pick your daughter’s name the old-fashioned way.&lt;/p&gt;

&lt;p&gt;So let’s look at a few of the techniques that NameGen uses.&lt;/p&gt;

&lt;p&gt;1. We start out in Google Sheets, first dropping a list of real names into column A, then slicing it into overlapping three-letter segments using the formula &lt;code&gt;=MID($A2,COLUMN(B2)-1,3)&lt;/code&gt; (that’s the version of the formula you’d use in cell B2; from there, just copy and paste the formula across the rest of the sheet and the cell references will update accordingly). &lt;a href="https://docs.google.com/a/google.com/spreadsheet/ccc?key=0AkG1UdyJGrY6dHZjRDhJZU9ZY3N1a091X1VMZ1hLQ0E#gid=1"&gt;Here’s a sample of one of the spreadsheets&lt;/a&gt; so you can see how the data is set up.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://1.bp.blogspot.com/-KF0VfnEsgc0/UMo_ni1Ox7I/AAAAAAAAA3k/Vv3TO3fJilI/s1600/namegen2.png" imageanchor="1" style=""&gt;&lt;img border="0" width="520" src="http://1.bp.blogspot.com/-KF0VfnEsgc0/UMo_ni1Ox7I/AAAAAAAAA3k/Vv3TO3fJilI/s520/namegen2.png" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2. We then create a &lt;a href="http://support.google.com/drive/bin/answer.py?hl=en&amp;answer=1272898"&gt;pivot table&lt;/a&gt; for each column in that first sheet, just summarizing the column by &lt;code&gt;COUNTA&lt;/code&gt; (the number of times each segment occurs). For example, since Lakisha, Nakia, and Nakisha (from our list of real names) share “aki” as letters 2 through 4, the pivot table for Segment 2 shows “aki: 3.”&lt;/p&gt;

&lt;p&gt;&lt;a href="http://4.bp.blogspot.com/-PG9WoA0Ec2g/UMo_oNl_wnI/AAAAAAAAA3w/3uRssbjDLhs/s1600/namegen3.png" imageanchor="1" style=""&gt;&lt;img border="0" width="520" src="http://4.bp.blogspot.com/-PG9WoA0Ec2g/UMo_oNl_wnI/AAAAAAAAA3w/3uRssbjDLhs/s520/namegen3.png" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The plan is that NameGen will randomly pick one of the starting three-letter segments, then look at the last two letters of its selection so that it can find an overlapping segment from the next column. The script then uses the pivot-table statistics to weight its selections toward more common segments. It continues until a segment ends in a blank. This diagram shows how it might build the name Calina:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://3.bp.blogspot.com/-b3dHaxMpzJI/UMo_oteAm4I/AAAAAAAAA38/CDwRwc8mzyE/s1600/namegen4.png" imageanchor="1" style=""&gt;&lt;img border="0" width="520" src="http://3.bp.blogspot.com/-b3dHaxMpzJI/UMo_oteAm4I/AAAAAAAAA38/CDwRwc8mzyE/s520/namegen4.png" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3. This is where Apps Script takes over. Just once per source list of names, we run the utility function below (shown slightly simplified) to convert the &lt;a href="https://developers.google.com/apps-script/storing_data_spreadsheets"&gt;spreadsheet data&lt;/a&gt; to a more useful format and store it in &lt;a href="https://developers.google.com/apps-script/scriptdb"&gt;ScriptDb&lt;/a&gt;. The script can then pull the data from ScriptDb in about 0.5s, versus about 5s to read directly from the spreadsheet. Note that we’re using &lt;a href="https://developers.google.com/apps-script/script_user_properties"&gt;Script Properties&lt;/a&gt; to store the spreadsheet ID rather than cluttering up the code with extra variables.&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
function updateDb() {
  var language = 'americanFemale';

  // Look up the spreadsheet ID in Script Properties, then grab its sheets. 
  var ssId = ScriptProperties.getProperty(language);
  var sheets = SpreadsheetApp.openById(ssId).getSheets();
  var dictSize = sheets[0].getLastRow() - 1;
  var segment = {};

  // Transform each sheet into the segment object we want later.
  for (var i = 0; i &lt; sheets.length; i++) {    

    // Retrieve the list of real names (first loop) or a pivot table.
    if (i === 0) {
      segment.data = sheets[0].getRange('A:A').getValues();
    } else {
      segment.data = sheets[i].getDataRange().getValues();
    }
    
    // Store other properties so we can retrieve the right record later.
    segment.index = i;
    segment.language = language;
    segment.size = dictSize;

    // Save the object as a ScriptDb record, then start the loop again.
    ScriptDb.getMyDb().save(segment);
  }
}
&lt;/pre&gt;

&lt;p&gt;4. Now, every time the app runs, it jumps straight to the &lt;code&gt;generateNames()&lt;/code&gt; function shown below (again slightly simplified). After it queries the database, it’s straight JavaScript — but one Apps Script–specific trick you’ll notice is that we assemble the data into an array using &lt;code&gt;segments[current.index] = current.data&lt;/code&gt; rather than &lt;code&gt;segments.push(current.data)&lt;/code&gt;. Because ScriptDb returns the records in an unpredictable order, we gave our objects an &lt;code&gt;index&lt;/code&gt; property to store the correct order.&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
function generateNames(language, numNames) {
  
  // Query the database to find all results for this language.
  var results = ScriptDb.getMyDb().query({language: language});
  var current = {};
  var segments = [];
  
  // Assemble the DB records into an array so we can pass it around.
  while (results.hasNext()) {
    current = results.next();
    segments[current.index] = current.data;
  }
  
  var names = [];
  var segment = '';
  
  for (var i = 0; i &lt; numNames; i++) {
    var name = '';
    
    // For each requested name, pick one segment, making
    // sure it overlaps with the previous two letters.    
    for (var j = 1; j &lt; segments.length; j++) {
      segment = randomSegment(segments[j], name);
      name = name.slice(0, name.length - 2);
      name += segment;
      
      // If the segment wasn't full length (end of a name), done!
      if (segment.length &lt; 3) {
        break;
      }
    }
    
    names.push(name);
  }
  
  return names;
}
&lt;/pre&gt;

&lt;p&gt;I haven’t explained the &lt;code&gt;randomSegment()&lt;/code&gt; function, but you can probably guess at how it works based on the description above. Still, if you want to dig in further, you can &lt;a href="https://script.google.com/a/google.com/d/1rvHw88PR04Su2FBFzf19v3SOemCOPGzgiWeu21jCagUayhBBgxeEn-Hj/edit"&gt;view the full source code here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;5. The only remaining step is to expose the results to the world through a web app. Apps Script provides several ways of doing this; I used &lt;a href="https://developers.google.com/apps-script/html_service"&gt;Html Service&lt;/a&gt;, but didn’t require any of the advanced features. Here’s how little HTML we need to turn NameGen into a functional app:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
&amp;lt;html&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;script&amp;gt;
      function sendRequest() {
        var language = document.getElementById('language').value;
        var numNames = document.getElementById('numNames').value;
        google.script.run.withSuccessHandler(updateField).
            generateNames(language, numNames);
      }
    
      function updateField(names) {
        var output = "";
        for (var i = 0; i &lt; names.length; i++) {
          output += (names[i] + '&amp;lt;br/&amp;gt;');
        }
        document.getElementById('resultsBox').innerHTML = output;
      }
    &amp;lt;/script&amp;gt;
    &amp;lt;select id="language"&amp;gt;
      &amp;lt;option value="americanFemale"&amp;gt;American Females&amp;lt;/option&amp;gt;
      &amp;lt;option value="americanMale"&amp;gt;American Males&amp;lt;/option&amp;gt;
      &amp;lt;option value="american"&amp;gt;American Towns&amp;lt;/option&amp;gt;
      &amp;lt;option value="british"&amp;gt;British Towns&amp;lt;/option&amp;gt;
      &amp;lt;option value="french"&amp;gt;French Towns&amp;lt;/option&amp;gt;
      &amp;lt;option value="irish"&amp;gt;Irish Towns&amp;lt;/option&amp;gt;
      &amp;lt;option value="italian"&amp;gt;Italian Towns&amp;lt;/option&amp;gt;
      &amp;lt;option value="spanish"&amp;gt;Spanish Towns&amp;lt;/option&amp;gt;
    &amp;lt;/select&amp;gt;
    &amp;lt;select id="numNames"&amp;gt;
      &amp;lt;option value=1&amp;gt;1&amp;lt;/option&amp;gt;
      &amp;lt;option value=10 selected&amp;gt;10&amp;lt;/option&amp;gt;
      &amp;lt;option value=100&amp;gt;100&amp;lt;/option&amp;gt;
      &amp;lt;option value=1000&amp;gt;1000&amp;lt;/option&amp;gt;
    &amp;lt;/select&amp;gt;
    &amp;lt;input id="generateButton" type="button"
     value="Generate" onclick="sendRequest()"&amp;gt;
    &amp;lt;div id="resultsBox"&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;

&lt;p&gt;And presto chango, you have a web app that harnesses the tremendous power of Google’s infrastructure … to produce names that could only ever exist in a parallel universe. It’s like Adriano Celentano’s "Prisencolinensinainciusol" — a convincing rendition of an American pop song, unless you actually speak English, in which case it’s total gibberish.&lt;/p&gt;
&lt;br/&gt;
&lt;iframe width="520" height="390" src="http://www.youtube.com/embed/FcUi6UEQh00" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;
&lt;br/&gt;
&lt;table cellpadding="5" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr style="background-color: #f2f2f2;"&gt;&lt;td&gt;&lt;img class="profile" src="http://1.bp.blogspot.com/-L5vafQapGkU/UMpDehHOJ8I/AAAAAAAAA4o/SaodIw1XPDI/s400/dan-lazin%2B%25281%2529.JPG" /&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;span class="largefont"&gt;Dan Lazin&lt;/span&gt; &amp;nbsp;   &lt;a class="alt" href="https://plus.google.com/109828037675019009042" rel="me" target="_blank"&gt;profile&lt;/a&gt; | &lt;a class="alt" href="http://twitter.com/danlazin" rel="me" target="_blank"&gt;twitter&lt;/a&gt;&lt;br /&gt;&lt;div class="bio"&gt;&lt;br /&gt;Dan is a technical writer on the Developer Relations team for Google Apps Script. Before joining Google, he worked as video-game designer and newspaper reporter. He has bicycled through 17 countries.&lt;/div&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;img src="http://feeds.feedburner.com/~r/GoogleAppsDeveloperBlog/~4/C02hg6jSJzQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://googleappsdeveloper.blogspot.com/feeds/4506449378303157075/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1377183911445147227&amp;postID=4506449378303157075&amp;isPopup=true" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/4506449378303157075?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/4506449378303157075?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GoogleAppsDeveloperBlog/~3/C02hg6jSJzQ/kicking-apps-and-making-names.html" title="Kicking Apps and Making Names" /><author><name>Google Apps Developer Blog Editor</name><uri>http://www.blogger.com/profile/07808045840831274565</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-NIap28cHzRg/UMpDefAdMUI/AAAAAAAAA4c/IyQVcfongHU/s72-c/namegen1%2B%25281%2529.png" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://googleappsdeveloper.blogspot.com/2013/01/kicking-apps-and-making-names.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0QBR3Y-eip7ImA9WhNVEUw.&quot;"><id>tag:blogger.com,1999:blog-1377183911445147227.post-3569907392449059770</id><published>2012-12-21T10:42:00.000-08:00</published><updated>2012-12-21T10:42:36.852-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-12-21T10:42:36.852-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Apps Script" /><category scheme="http://www.blogger.com/atom/ns#" term="Guest Post" /><title>Managing Projects with Gantt Charts using Google Apps Script</title><content type="html">&lt;p&gt;&lt;i&gt;Editor’s Note: Guest author Ronald Dahrs runs &lt;a href="https://sites.google.com/site/forscaleprojectsite/"&gt;Forscale&lt;/a&gt;, an IT and project management company based in the Netherlands. -- Arun Nagarajan&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;Google Apps is well-suited for project management because it’s a cloud-based productivity suite that helps you and your team connect and get work done from anywhere on any device. Using Google Apps Script, we can push the capabilities even further to create advanced scheduling and management tools. A common tool in project management circles is the &lt;a href="http://en.wikipedia.org/wiki/Gantt_chart"&gt;Gantt chart&lt;/a&gt;: a schedule of the tasks in the project and how they relate to each other over time.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://2.bp.blogspot.com/-PAkTVnZF-c8/UNFXIshURQI/AAAAAAAAA7A/VTOXUu3usug/s1600/gantt1.png" imageanchor="1" style=""&gt;&lt;img border="0" width="520" src="http://2.bp.blogspot.com/-PAkTVnZF-c8/UNFXIshURQI/AAAAAAAAA7A/VTOXUu3usug/s520/gantt1.png" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The spreadsheet that generated that Gantt chart is &lt;a href="https://drive.google.com/previewtemplate?id=0AhiVMVNQW_vOdHNPbm10cW9ZTjBocFB4SDRPNXBVWlE&amp;mode=public"&gt;available in the template gallery today&lt;/a&gt;. In this post, we’ll explore the basics of how the template works and explain a few of the Apps Script techniques that transform Google Sheets into such a powerful project management tool.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://4.bp.blogspot.com/-FSRa1zOOE-8/UNFXJUsXTYI/AAAAAAAAA7M/YKWdKaSqOEs/s1600/gantt2.png" imageanchor="1" style=""&gt;&lt;img border="0" width="520" src="http://4.bp.blogspot.com/-FSRa1zOOE-8/UNFXJUsXTYI/AAAAAAAAA7M/YKWdKaSqOEs/s520/gantt2.png" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you open the template, you’ll see stubs for each type of task, but the screenshot above shows an example of a slightly larger project plan — in fact, the same data used to generate the Gantt chart below.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://3.bp.blogspot.com/-zRbTi0iFyn0/UNFXKYw-fFI/AAAAAAAAA7Y/sFMTjDnWugY/s1600/gantt2b.png" imageanchor="1" style=""&gt;&lt;img border="0" width="520" src="http://3.bp.blogspot.com/-zRbTi0iFyn0/UNFXKYw-fFI/AAAAAAAAA7Y/sFMTjDnWugY/s520/gantt2b.png" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The template’s sophisticated formulas rely on the structure of the table to enable schedule awareness and task dependencies. However, we still ensure that the user can rename, rearrange, or add columns by using a hidden header to identify each column. This diagram demonstrates the spreadsheet’s structure:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://2.bp.blogspot.com/-LAfYKGlL4p0/UNFEgAua8HI/AAAAAAAAA6I/knSIgHWyU5o/s1600/gantt3.png" imageanchor="1" style=""&gt;&lt;img border="0" width="520" src="http://2.bp.blogspot.com/-LAfYKGlL4p0/UNFEgAua8HI/AAAAAAAAA6I/knSIgHWyU5o/s520/gantt3.png" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In Apps Script, we use the spreadsheet’s &lt;code&gt;&lt;a href="https://developers.google.com/apps-script/understanding_events"&gt;onEdit()&lt;/a&gt;&lt;/code&gt; event to monitor user interaction with the schedule portion of the spreadsheet and update the Gantt chart accordingly. The powerful JavaScript language does all the required summary calculations based on the provided dates and completion percentages.&lt;/p&gt;

&lt;p&gt;We have also used Apps Script’s &lt;code&gt;&lt;a href="https://developers.google.com/apps-script/class_spreadsheet#addMenu"&gt;addMenu()&lt;/a&gt;&lt;/code&gt; method to build a custom menu that calls row-oriented functions like indenting tasks to get a so-called Work Breakdown Structure with summary tasks. If you just want to see an overview, the custom menu allows you to collapse tasks, which we accomplished through the &lt;code&gt;&lt;a href="https://developers.google.com/apps-script/class_sheet#hideRows"&gt;hideRows()&lt;/a&gt;&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;For changes that do not trigger an &lt;code&gt;onEdit()&lt;/code&gt; event (for example, clearing a row), the user can use the menu’s Refresh command to recalculate the schedule.&lt;/p&gt;

&lt;p&gt;The template stores user preferences as &lt;a href="https://developers.google.com/apps-script/service_properties"&gt;Script Properties&lt;/a&gt; and offers an interactive user interface built in &lt;a href="https://developers.google.com/apps-script/class_uiapp"&gt;UiApp&lt;/a&gt; to change those settings:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://3.bp.blogspot.com/-tAWYfJDK4sA/UNFEgpgFrfI/AAAAAAAAA6U/velcsCUHdZ4/s1600/gantt4.png" imageanchor="1" style=""&gt;&lt;img border="0" height="400" width="339" src="http://3.bp.blogspot.com/-tAWYfJDK4sA/UNFEgpgFrfI/AAAAAAAAA6U/velcsCUHdZ4/s400/gantt4.png" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, to render the Gantt chart, we use cell background colors to visually group and highlight the appropriate cells. This creates the effect of a continuous calendar with clearly visible start and finish dates for each task.&lt;/p&gt;

&lt;pre class="prettyprint"&gt;var ganttColors = ganttRange.getBackgroundColors();
var ganttValues = ganttRange.getValues();

// update Gantt colors and values 
ganttRange.setBackgroundColors(ganttColors).setValues(ganttValues);
&lt;/pre&gt;

&lt;table cellpadding="5" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr style="background-color: #f2f2f2;"&gt;&lt;td&gt;&lt;img class="profile" src="http://2.bp.blogspot.com/-TCh7kmIoSZ0/UNFEhd5tGPI/AAAAAAAAA6g/C_-W1RckcHc/s400/ronald-dahrs.png" /&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;span class="largefont"&gt;Ronald Dahrs&lt;/span&gt;
&lt;br /&gt;&lt;div class="bio"&gt;&lt;br /&gt;Ronald combines his knowledge of project management and software solutions at his company, &lt;a href="https://sites.google.com/site/forscaleprojectsite/"&gt;Forscale&lt;/a&gt;. He believes Google Apps is an excellent platform for online project management. He uses Google Apps Script to integrate the services to manage a wide range of projects.
&lt;/div&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;img src="http://feeds.feedburner.com/~r/GoogleAppsDeveloperBlog/~4/3GwTqBF40Zc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://googleappsdeveloper.blogspot.com/feeds/3569907392449059770/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1377183911445147227&amp;postID=3569907392449059770&amp;isPopup=true" title="9 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/3569907392449059770?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/3569907392449059770?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GoogleAppsDeveloperBlog/~3/3GwTqBF40Zc/managing-projects-with-gantt-charts.html" title="Managing Projects with Gantt Charts using Google Apps Script" /><author><name>Google Apps Developer Blog Editor</name><uri>http://www.blogger.com/profile/07808045840831274565</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-PAkTVnZF-c8/UNFXIshURQI/AAAAAAAAA7A/VTOXUu3usug/s72-c/gantt1.png" height="72" width="72" /><thr:total>9</thr:total><feedburner:origLink>http://googleappsdeveloper.blogspot.com/2012/12/managing-projects-with-gantt-charts.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUEBQXkzeCp7ImA9WhNWGU4.&quot;"><id>tag:blogger.com,1999:blog-1377183911445147227.post-5458946114125757806</id><published>2012-12-19T09:20:00.002-08:00</published><updated>2012-12-19T09:20:50.780-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-12-19T09:20:50.780-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Apps Script" /><title>The Hottest Script in Hollywood</title><content type="html">&lt;p&gt;In just a few hours at the recent Apps Script hackathon in Los Angeles, we saw attendees build everything from website monitoring to room booking to financial tracking apps. For those of you who couldn’t make it, attendees were given a &lt;a href="https://developers.google.com/apps-script/your_first_script"&gt;brief introduction to Apps Script&lt;/a&gt; and a few hours to let their imaginations run wild. Apps Script’s ease of use enabled them to quickly create fully functioning, useful apps. Here are a few interesting things we saw from local developers:&lt;/p&gt;
&lt;br/&gt;
&lt;h3&gt;Website Monitor by Eduardo Arino de la Rubina&lt;/h3&gt;

&lt;p&gt;These days, small businesses are quickly increasing their online presence; a website outage during a critical period can be devastating to a mom-and-pop shop. Eduardo realized that existing network-monitoring solutions require a significant investment in technology and infrastructure that is beyond the reach of many small-business users. Using Apps Script’s &lt;a href="https://developers.google.com/apps-script/service_urlfetch"&gt;UrlFetch&lt;/a&gt; and &lt;a href="https://developers.google.com/apps-script/service_spreadsheet"&gt;Spreadsheet&lt;/a&gt; services, he was able to quickly create a website monitor packaged in an easy-to-use spreadsheet that, given a list of URLs, tries to fetch each one and records the latency and content length.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/4137612"&gt;The code is available here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://2.bp.blogspot.com/-bQS796FQLrc/UM-ncoHyH5I/AAAAAAAAA5M/BwF4rfEH1EM/s1600/losangeles1.png" imageanchor="1" style=""&gt;&lt;img border="0" width="520" src="http://2.bp.blogspot.com/-bQS796FQLrc/UM-ncoHyH5I/AAAAAAAAA5M/BwF4rfEH1EM/s520/losangeles1.png" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;br/&gt;

&lt;h3&gt;Get A Room by &lt;a href="https://plus.sandbox.google.com/104088470374181384933"&gt;Danny Favela&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Get A Room allows users to book meeting rooms by taking advantage of Apps Script’s tight &lt;a href="https://developers.google.com/apps-script/service_calendar"&gt;integration with Google Calendar&lt;/a&gt; and events. The app, built entirely on a &lt;a href="http://www.google.com/intl/en/chrome/devices/"&gt;Chromebook&lt;/a&gt; utilizing Apps Script's cloud friendliness, displays building floorplans with buttons that users can click to book a room. In response to a booking request, the app fetches the room’s calendar and creates a new event. It also updates the UI by replacing the floor plan with a modified image to show the newly booked room. Here is a snippet of the booking code:&lt;/p&gt; 

&lt;pre class="prettyprint"&gt;
// Click handler for the interaction to book a room
function bookBoardroomHandler(e) {
 var app = UiApp.getActiveApplication();

 // Perform the calendar-booking operations
 bookBoardroom();
 
 // Swap the images as visual confirmation
 app.remove(app.getElementById('imageDefaultLayout'));
 app.add(app.getElementById('imageBoardroom'));

 app.close();
 return app;
}

function bookBoardroom(e) {
 var calendarBoardroom = CalendarApp.getCalendarsByName("Boardroom");
 calendarBoardroom[0].createEventFromDescription("Boardroom Meeting");  
}
&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://4.bp.blogspot.com/-rS3ChO4_dH0/UM-ndWsdC8I/AAAAAAAAA5Y/wqzmZW5M-_o/s1600/losangeles2.png" imageanchor="1" style=""&gt;&lt;img border="0" width="520" src="http://4.bp.blogspot.com/-rS3ChO4_dH0/UM-ndWsdC8I/AAAAAAAAA5Y/wqzmZW5M-_o/s520/losangeles2.png" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;br/&gt;

&lt;h3&gt;Stock Info by Matt Kaufman&lt;/h3&gt;

&lt;p&gt;Matt decided to build a web service that provides information about publicly traded stocks. The app’s backend consists of a spreadsheet with stock symbols of interest. Using Apps Script’s &lt;a href="https://developers.google.com/apps-script/service_finance"&gt;FinanceService&lt;/a&gt;, Matt loops through the spreadsheet on a timed trigger and appends the latest stock information for each symbol. He then uses &lt;a href="https://developers.google.com/apps-script/service_html"&gt;HtmlService&lt;/a&gt; to create a web app that outputs an XML page of the stock info based on a symbol parameter in the URL. Here’s a picture of his script in action:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://4.bp.blogspot.com/-XgELdXBRxQY/UM-nd7bvboI/AAAAAAAAA5k/Yd1GEfgybMI/s1600/losangeles3.jpg" imageanchor="1" style=""&gt;&lt;img border="0" height="400" width="195" src="http://4.bp.blogspot.com/-XgELdXBRxQY/UM-nd7bvboI/AAAAAAAAA5k/Yd1GEfgybMI/s400/losangeles3.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These are just some examples of how quickly useful apps can be created with Apps Script. Thanks to all the attendees for coming out! If you couldn’t make it to the hackathon, check out these &lt;a href="https://developers.google.com/apps-script/articles"&gt;tutorials&lt;/a&gt; to see how you can get started making great apps.&lt;/p&gt;

&lt;br/&gt;

&lt;table cellpadding="5" cellspacing="0"&gt;&lt;tbody&gt;
&lt;tr style="background-color: #f2f2f2;"&gt;&lt;td&gt;&lt;img class="profile" src="https://sites.google.com/site/developeradvocates/image/kalyan_reddy.png"&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;span class="largefont"&gt;Kalyan Reddy&lt;/span&gt;   &lt;a class="alt" href="https://plus.google.com/u/0/104332150690924044386/posts" rel="me" target="_blank"&gt;profile&lt;/a&gt; | &lt;a class="alt" href="http://stackoverflow.com/users/1666956/kalyan-reddy"&gt;Stack Overflow&lt;/a&gt;&lt;br&gt;
&lt;div class="bio"&gt;&lt;br&gt;
Kalyan is a Developer Programs Engineer on the Google Apps Script team based in NYC. He is committed to increasing developer productivity by helping them fully utilize the power of Apps Script. In his free time, he enjoys participating in the Maker community and hacking together robots.
&lt;/div&gt;&lt;br&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;img src="http://feeds.feedburner.com/~r/GoogleAppsDeveloperBlog/~4/GFWi8RbL9no" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://googleappsdeveloper.blogspot.com/feeds/5458946114125757806/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1377183911445147227&amp;postID=5458946114125757806&amp;isPopup=true" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/5458946114125757806?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1377183911445147227/posts/default/5458946114125757806?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GoogleAppsDeveloperBlog/~3/GFWi8RbL9no/the-hottest-script-in-hollywood.html" title="The Hottest Script in Hollywood" /><author><name>Google Apps Developer Blog Editor</name><uri>http://www.blogger.com/profile/07808045840831274565</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-bQS796FQLrc/UM-ncoHyH5I/AAAAAAAAA5M/BwF4rfEH1EM/s72-c/losangeles1.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://googleappsdeveloper.blogspot.com/2012/12/the-hottest-script-in-hollywood.html</feedburner:origLink></entry></feed>
