Pages

Friday, March 13, 2015

Manymoon sees 30 higher conversions on Google Apps Marketplace

Editors Note: This post was written by Amit Kulkarni, CEO at Manymoon, a company that provides team and project management software. We invited Manymoon to share their experiences building an application on top of Google Apps utilizing some of our APIs.

An Idea

We started Manymoon with the idea of bringing social communications to the workplace. Not because it was cool, but because we think the best way to get work done is with the help of the people around you while still minimizing interruptions.

Like most start-ups, we wanted to build something we’d use ourselves. As heavy Google Apps users, we immediately saw the benefit of integrating Manymoon with Google Apps for tracking tasks or projects.

We also knew that professionals have unique requirements:
  • Utility - professionals are busy throughout the work day and get judged on productivity. Any app they use needs to provide tangible value with immediate gratification. And what’s more satisfying than completing a task or project?
  • Security - they need the ability to control what’s shared and with whom.

This led us to create Manymoon: a social productivity tool. It allows you to leverage your professional network to get work done. That means doing things like tracking conversations, managing projects, completing tasks and sharing documents. That was the easy part, now we just had to build it and find customers.




Finding Customers

The market opportunity speaks for itself: Google Apps has over 30 million users spanning over 3 million businesses. It’s also a growing business since they’re signing up over 3,000 new businesses per day. We would be in good shape if we got a small fraction of this flow.

Most importantly, the Google Apps Marketplace brings qualified customers who are comfortable using the cloud to run their business. Google Apps customers understand the value of:
  • Not having to install or maintain software
  • Software that requires minimal training
  • Self-service software (they don’t require significant amount of in-person sales or support).
These are critical traits since they allowed us to focus on building a great product instead of having to ramp up other parts of the organization (e.g., hiring sales people, support engineers, etc).

How We Did It

As a start-up, one of our advantages is time to market. There are numerous features that would have normally taken us months to develop but we accelerated the process by leveraging a variety of Google APIs and products.

Google Docs
Attach a Google Doc to a task or project and Manymoon will automatically handle the sharing permissions. This is the feature that consistently receives the most “wow” comments from customers.

Google Calendar
Keep your calendar automatically updated with relevant tasks and project information. We saved months that would have been required to build features such as reminders, views and meeting requests.

OpenID & Google Universal Navigation

Business customers already trust Google with their data, and this significantly reduces the friction in activating users. And with Google Universal Navigation, new users can experience Manymoon immediately without even having to register. Using Single Sign-On means users can move seamlessly from Google Apps to Manymoon without needing to re-enter their credentials.

Google Contacts

Contact integration via Google Contact API makes it incredibly easy to assign a task to someone or invite them to a project. Just enter their name! No more remembering email addresses or having to import contacts.

Gadgets!
Our customers are Google Apps customers first and foremost and this makes it simple to use Manymoon in the environment they’re already used to. We support a Gmail Contextual Gadget so users can create tasks and projects without ever leaving their inbox. And a Google Sites/iGoogle gadget allows project data to be part of more complex wiki and portal pages that customers build. Ultimately, Google Gadgets significantly reduce the friction for users to create and track projects.

The Results

The results have been fantastic. Since the launch of the Google Apps Marketplace in March, we’ve been signing up as many as 1,000 new businesses per week ... and that’s with no sales or marketing people in our company. These customers are finding us on their own in the Google Apps Marketplace, adding the app and getting engaged with it.

Google Apps Marketplace customers upgrade to a premium edition of Manymoon at a 30% higher rate than non-Google Apps Marketplace customers. The best part, however, is that our monthly registrations increased by 150% since the launch of Google Apps Marketplace. And that’s where the Marketplace really excels, it provides large enough volumes to make the Freemium business model work.

We also closely monitor business sign-ups since their users activate over a period of time. If a business with 1,000 employees signs up to Manymoon, some fraction of those users will use Manymoon in the 1st day. But a larger fraction will use it in the first week and and an even larger in the first month.

What We’ve Learned

We think there are three ingredients that are important to sustaining a large number of business sign-ups from the Google Apps Marketplace:

1) Appeal to a broad audience - Google Apps customers comprise all types of industries and job functions. Manymoon is broad enough to apply to most of them, so we cast the widest net and try to appeal to as many as possible.

2) Integrate deeply - of course most all Google Apps customers use Gmail. But each customer has its own mix of Google Apps they use (e.g., Google Docs + Gmail, Google Sites + Gmail, etc). We built Manymoon to be flexible enough to accommodate any of these mixes.

3) Demonstrate immediate value - logging in using a Google Apps account is the price of admission (literally). To really engage customers, you have to very quickly demonstrate additional ways your app works with Google Apps. We do this during the registration process.

How To Get Started

Google provides open APIs with very good documentation that can be accessed here. They also have a simple and transparent process for listing your app. We were able to find everything we needed to build and integrate Manymoon with Google Apps.

Want to weigh in on this topic? Discuss on Buzz

Read more »

Thursday, March 12, 2015

Email address validation with Actions in the Inbox and Mandrill

We launched Actions in the Inbox at Google I/O 2013 as a quick way for users to get things done directly from Gmail. Integrating with this technology only requires adding some markup to an email to define what the message is about and what actions the user can perform.

We support a variety of action types covering common scenarios such as adding a movie to a queue, product reviews, or other even pre-defined requests. Especially popular with senders is the One-Click Action to validate a user’s email address, as shown below:


If you are using Mandrill, the email infrastructure service from MailChimp, writing a Python app to send one of those emails, only takes a few lines of code! Take a look at this example:

import mandrill

# Replace with your own values
API_KEY = YOUR_API_KEY
FROM_ADDRESS = YOUR_FROM_ADDRESS
TO_ADDRESS = YOUR_TO_ADDRESS
SUBJECT = Please validate your email address

HTML_CONTENT = """
<html>
 <body>
   <script type=application/ld+json>
   {
     "@context": "http://schema.org",
     "@type": "EmailMessage",
     "action": {
       "@type": "ConfirmAction",
       "name": "Confirm Registration",
       "handler": {
         "@type": "HttpActionHandler",
         "url": "https://mydomain.com/validate?id=abc123"
       }
     }
   }
   </script>
   <p>Please click on this link to validate your email address:</p>
   <p><a href="https://mydomain.com/validate?id=abc123">https://mydomain.com/validate?id=abc123</a></p>
 </body>
</html>
"""

# Instantiate the Mandrill client with your API Key
mandrill_client = mandrill.Mandrill(API_KEY)

message = {
html: HTML_CONTENT,
subject: SUBJECT,
from_email: FROM_ADDRESS,
to: [{email: TO_ADDRESS}],
}

result = mandrill_client.messages.send(message=message)

To run this app, just replace the API key with the credentials from your Mandrill account and configure the sender and recipient addresses. You should also edit the HTML content to provide your action handler URL, and customize the messaging if you want.

You can use Actions in the Inbox to reduce the friction and increase the conversion rate. Please note that you are not limited to validating email addresses: you can also review products and services, reply to event invitations, and much more.

For more information, please visit our documentation at https://developers.google.com/gmail/actions. You can also ask questions on Stack Overflow, with the tag google-schemas.

Claudio Cherubino   profile | twitter | blog

Claudio is an engineer in the Gmail 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.

Read more »

Facilitating a retrospective with 50 people in an hour

As one of the volunteers at Agile 2012 I was honoured to be asked to facilitate the volunteer retrospective.

There were a few constraints that made this retrospective challenging. First, due to our volunteer responsibilities we had just under an hour to eat lunch and complete the retrospective. Second, there are about 50 volunteers - allowing everyone to have a voice in such a short time frame would be a challenge. Third, it was important to all of us to celebrate the things that went well and also give a clear, prioritized list of ideas to future volunteer teams.

After discussing the constraints and various facilitation options with some of you, here is what we did:

1. Instead of building a timeline of our experiences we held the retrospective in our volunteer room. Throughout the week we had plastered the walls with our schedules (including happy/sad faces), guidelines, issues, ideas for improvement, etc which then served as visual provocations for the retrospective.

Picture courtesy of Adam Yuret
2. We used silent brainstorming liberally in order to speed up the retrospective while still including every voice. In general we followed the Rising Patton Fusion retrospective model that combines silent brainstorming, silent grouping, and silent voting.

3. We split into 5 groups of 10. Each group would perform a retrospective step together before sharing their results with the larger group.

4. The two major prompts we used in the retrospective were:
The combined greats
- "It was great because...". Each table wrote these in silence, read them out loud to each other, grouped them in silence and then named the groups. The named groups were then shared with the rest of the tables and consolidated into one larger list.
- "Do differently". Once again, each table wrote these in silence, read them out loud to each other, and then voted in silence. The top 3 items from each table were again shared with the rest of the tables and consolidated into one larger list.

5. Finally, we posted pictures of all the results (yes, every single post-it note) on the Agile Conference Volunteers Facebook page for later reference and comments.

It was a lot of fun and seemed to work well given the constraints. We achieved our goal of giving everyone a voice in a short time period, celebrating what went well, and also producing a nice list of actionable ideas for next year. Anything you would do differently?

Subscribe to Winnipeg Agilist by Email
Read more »

A short story about co location

The post I created yesterday reminded me of this story:

A team I was working on was asked to sit together in a rather cramped area. Five of us (two developers, one application architect, one tester, one business analyst) were asked to share a very small area about the size of a typical office. The business analyst had desk space equivalent to the size of a typical end table; there were monitors perched precariously above us on small shelves; we shared one phone; and the limited wall space we had was covered with our visible boards and stickies. Fun!

As we reflected on our space at the end of the project, this comment was made from one of the developers: "On the bright side, I dont think I looked at the requirements document once. I just turned to the business analyst beside me and asked her what needed to be done!" Co-location for the win.

"The most efficient and effective method of conveying information to and within a development team is face-to-face conversation" - Agile Manifesto
Read more »

Domain user management with Apps Script

Managing the user accounts in a Google Apps domain can be a daunting task when you have hundreds or thousands of them and you have no tools to automate the process. The Google Apps Provisioning API allows developers to write user management applications in the programming language of their choice, but many system administrators prefer a script-based solution instead. The recently launched UserManager Apps Script service fills the gap, providing Google Apps domain administrators an easy way to automate tasks such as batch user creation or update.

With the new Apps Script service, creating a user will be as easy as writing a single line of code:

var user = UserManager.createUser("newuser", "John", "Smith", "mypassword");

The UserManager service also makes it easy to perform the same task on each account in the domain. The following sample shows how you can force all users to change their passwords at the next login:

var users = UserManager.getAllUsers();
for (var i in users) {
users[i].setChangePasswordAtNextLogin(true);
}

Calls to the UserManager service can also be scheduled to run hourly or daily, or in response to certain events thanks to Apps Script Triggers.

Interested in what else you can do with the UserManager service? Please check the documentation and get in touch with us on the the forum for any questions about its usage or to share more info about your project with the community.

Claudio Cherubino   profile | twitter | blog

Claudio is a Developer Programs Engineer working on Google Apps APIs and the Google Apps Marketplace. Prior to Google, he worked as software developer, technology evangelist, community manager, consultant, technical translator and has contributed to many open-source projects, including MySQL, PHP, Wordpress, Songbird and Project Voldemort.

Read more »

Wednesday, March 11, 2015

It’s the system not and the people

I live and work with two phrases in my head that are important to me:
“It’s the system, not the people” – Deming
 And, paradoxically:
“It’s all about the people” – a statement heard often at Protegra that we try to use to guide how we work together.
An event this weekend helped me to understand these seemingly contradictory ideas. My brother (as coach) and nephew (as player) are participating in the junior varsity (gr. 9/10) provincial basketball championships. Last night I was able to watch them play in the semi-finals and could see both of the quotes above at work.

“It’s the system, not the people”

After an exciting victory by my nephew’s team, I overheard a conversation between two neutral parties as they did a postmortem on the game. In their assessment they agreed that both teams were skilled, gave it everything that they had, and played with passion. The main difference between the two teams was that the winning team had a better defensive system – not better players, but a better system. While the opposing coach did his best to exhort his players to play smarter, take better shots, make better passes, avoid the red beads, and play harder defense, ultimately they were defeated by a better system. They didn’t lose this game because of “resources” (coaches, players and refs), they lost to a better system.

“It’s all about the people”

Let’s look at the game from another angle. It was my brother the coach (a person) who researched, introduced, and taught the system to the team. It was the players (people) who bought into and committed to playing within the system. Both the offensive and defensive systems used by the team are well chosen and effective because they depend on teamwork and collaboration. Their systems require all of them to act together – if one person steps outside of the system it breaks down. The systems do not rely on one or two heroes but on the team as a whole. The systems require people to learn together, improve together, and be engaged together. The systems are all about the people. A pretty neat life lesson for a group of gr. 10 boys.

So, yes “It’s the system, not the people”, and yes, “It’s all about the people.”
“We believe it’s all about people. We believe by systematically focusing on people, treating them as the heart of organizational systems, that success will follow for all.” – Protegra.
Subscribe to Winnipeg Agilist by Email
Read more »

I will continue using Chrome

I dont like to write about hot topics. Waste of time mostly since everyone tends to overpush it. But IE 9 Beta brings important points, so here is my resume:

1. Nicely implements Chrome logic of tabs and big screen for website
2. Speed is nicely improved, though the feeling of being stuck is still there
3. Its designed as it should be. The great MS feeling for design. Windows and Office users will LOVE it.

4. Downloading is as stupid as it can be.
5. Microsoft wants to loose its market share. Downloading it takes too many clicks. Installing is too many clicks. First use is too many clicks.
6. Microsoft want to loose its market share. You cant install it on WinXP.
7. Microsoft does NOT want people to download IE 9. Here is the exact way to NOT get it:
 - go to http://www.microsoft.com/en/us/default.aspx => CLICK FREE download
 - you come here http://www.microsoft.com/presspass/presskits/internetexplorer/ => CLICK Get it NOW
 - you come here http://www.beautyoftheweb.com/ => click Download NOW
 - another beautiful window arises telling you that it it Win7 or Vista only

As one of many Win XP users you give up. Not to mention Mac and Linux users. Youre just waste of Microsoft money.

OK, Microsoft really has a bad attitude towards web-download-use process. It is always a mess of unlogical 20-times confirmation of legal and ilegal and mostly legal notices. Questions about what you really want. Facts about the beauty of their products. Facts about pirates and illegal equipment. Facts about the features of the great Microsoft products.

I know, I bought Windows 7 once. After 30 minutes of WANTING TO BUY I gave up and called Microsoft to tell me where I can buy. After 10 minutes on phone (now thats a process!) I got info about Irish website where EU customers can buy it. So it was 50 minutes shopping for 1 Windows7.

But lets forget for a minute that Microsoft does NOT want people to buy their products. Forget that downloading their products is big pain for experienced users. Lets focus on beauty of the web, IE9, comparing to others.

IE9 passed the css test. Great, all that I ever wanted. But does this box seem to be having rounded corners ?

IE9

NO. So nothing will change actually. Well still need to develope websites for IE especially. Ugly. No further test needed.

I will continue using Chrome. Just because I dont care which version it is for more than a year. It just updates whenever theres something new. No download button. No Get it now button. No FREE download button. No Accept button. No legal notice. Just small, natural, evolutionary changes every once in a while. And normal css support.

And Im sure this is something all other browsers still need to learn. "Versions" are useless for users. They can be some marketing point, but needless and pointless in the future of browser wars.
Read more »

More ways for apps to write to Drive

Today we’re introducing two new ways for apps to build even richer integrations with Drive: app data folders and custom properties.

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 app data folder 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.

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.

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.

To learn more check out the technical documentation for both app data folders and custom properties, and if you have questions don’t hesitate to post on StackOverflow.

Nicolas Garnier Google+ | Twitter

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 OAuth 2.0 Playground.

Read more »

Download or print Google docs viewer file

Today I was amazed by not being able to properly print a Google Docs Viewer file. Not sure if that was due to some protection of the document, but it was really not nice. All I got from printing was the first page. Through PDF or direct print. No "Download" button or anything like it. I assume it is due to protection levels anyway.

After few minutes, the only solution possible was:

1. Open Firefox
2. Install "downthemall"
3. Scroll through all the file so all the images render
4. Select "DownThemAll" from the blank space in the centre of the page


Got all the images to my local disk, so then just selected them all and print (now this is really good feature in Windows 7, congratulations MS).
Read more »

Freemium model for enterprise software

The Freemium business model is normal for consumer applications, but can it work for enterprise software? Freemium usually means a free service with an "up sell" to paid premium subscriptions. Examples include Skype, LinkedIn, Flickr, Ancestry.com, Typepad, Dropbox, and many others. Freemium differs from Free Trial in that a free trial is the fully functional product but only for a limited time. Freemium is always free, but you can purchase additional features or service for a premium price.

Freemium business models usually involve a Free service, sometimes time limited or feature limited, supported by advertising. The ads rarely cover costs. The goal is to convert these free users to paid subscriptions. Most consumer services start with a $10 per user per month subscription and scale up to $20 or $50 per month based on a small, medium, large usage scale.

Enterprise software is also using the Freemium model, sometimes with higher prices commensurate with the power and functionality of the product. They all have slightly different measurements and cut-off points, but most have some notion of small, medium, large.

Most companies see a 1.5% to 5% conversion rates, with most of them averaging around 3%. That doesnt sound like much but they are reaching tens of thousands to hundreds of thousands of users...sometimes millions.

Here is some math. 100,000 free users convert to 3,000 paid users. If they pay $50 per user per month, that is $150K a month or $1.8M per year. That is an excellent revenue stream for small startups that typically have 3 to 5 employees. And, it is an annuity stream that continues to grow every year. By the 3rd or 4th year these small companies can be generating $5M to $10M a year, still with less than 10 employees. Most of these small companies dont take Venture Capital so they own the whole company. It is a pretty good cash flow business.

Recently at Google IO I moderated an all-star panel of VCs on the subject of Freemium in the enterprise.
Making Freemium work - converting free users to paying customers - Venture Capitalists, Brad Feld (Foundry Group), Dave McClure (500 Startups), Jeff Clavier (SoftTech VC), Matt Holleran (Emergence Capital) and Joe Kraus (Google Ventures) discussed strategies for building free products that can be upgraded to paid versions.

Some key points from the panel;

  • Your initial thoughts about how much customers will pay, and how much they will pay, is probably wrong
  • Start collecting usage statistics from day one, even if you dont have time to analyze them. These stats will help you understand which features customers really use, and what they are likely to pay for.
  • Customers tend to optimize for "least surprise" so they tend to purchase a service level one above what they think they will need. Think cell phone pricing models.
  • Gmail Enterprise is a good example of an enterprise Freemium product based on usage limits. The first 50 users are free, but convert to paid subscription over that.
  • Freemium works best where there is a "network effect" or where more free users contributing content or data makes the service more valuable.
  • Put your business model in beta at the same time you put your product in beta. Test several business model scenarios to see what works best.
  • Consumers dont pay for additional features, turning off advertisements, analytics, etc...but businesses may be very happy to pay for these things
  • Google Apps Marketplace is a great channel to get your product to Google Apps business customers.

Watch the video for more details and insight. This group of VCs has built lots of companies based on the Freemium business model. They have some great insights.

Read more »

Sheetcaster 3D in Apps Script

Editor’s note: This is a guest post by Thomas Coudray, Amaury de la Vieuville, and Ahmed Bougacha. Thomas, Amaury, and Ahmed attended the Google Apps Script Hackathon in Paris, and in this post they are sharing their creative use of Google Apps Script to render a 3D scene in a Google Spreadsheet. -- Jan Kleinert

Recently, we heard about the Google Apps Script Hackathon arriving in Paris, France. We did not know much about Apps Script - heck, even JavaScript! Perfect occasion to learn something. We spent most of the event hacking around with the ever-growing collection of Google APIs. As a tribute to the folks over at id Software, we settled on one of the most fun (however useless) ways to use it: rendering a 3D scene in a spreadsheet.

The rendering is done using a technique called ray-casting, made popular by the 90s id Software game Wolfenstein 3D. Ray-casting is a really brilliant and straightforward algorithm:

First, we render the background: color the upper (sky) and lower (floor) halves of the screen in different colors. We store the pixel colors in a matrix, the screen buffer:


screen = new Array(SIZE_Y);
for (var lin = 0; lin < SIZE_Y; lin++) {
screen[lin] = new Array(SIZE_X);
for (var col = 0; col < SIZE_X; col++) {
screen[lin][col] = colorToString((lin < MID) ? UPPER_BG_COLOR
: LOWER_BG_COLOR);
}
}

Note that we draw the screen only once the buffer is fully colored, to avoid the overhead of coloring cells individually.

Then for each column of the screen:

  1. Cast a ray
  2. Move along the ray until hitting a wall, calculate the distance to that wall
  3. Draw a column whose height is inversely proportional to that distance

The trick is in the drawing: the upper and lower halves of the screen are symmetrical in shape, and the only computed value is the display height of the wall. The screen really is just a fancy formatting for an integer array of columns.

The camera is represented using:

  • Its (real-valued) x/y coordinates in the map plane
  • Its angle relative to some predefined direction

We store these 3 values at the bottom of the sheet, to ensure persistence (else, each refresh would bring us back to the start location!).


function Camera() {
this.x = CAMERA_X;
this.y = CAMERA_Y;
this.theta = CAMERA_THETA;

this.saveToSheet = function(sheet) {
// The player state has to be saved between each frame
sheet.getRange(STORE_LIN, 1, 1, 1).setValue(this.x);
sheet.getRange(STORE_LIN, 2, 1, 1).setValue(this.y);
sheet.getRange(STORE_LIN, 3, 1, 1).setValue(this.theta);
};

this.readFromSheet = function(sheet) {
this.x = sheet.getRange(STORE_LIN, 1, 1, 1).getValue();
this.y = sheet.getRange(STORE_LIN, 2, 1, 1).getValue();
this.theta = sheet.getRange(STORE_LIN, 3, 1, 1).getValue();
};

...
}

The map is a logical matrix, thus limiting us to discrete boxes for walls: for every cell, there either is (1), or is not (0), a wall:


// starting 10x10 map
var S = 10;
var map =
[
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 0, 1, 1, 0, 1, 0, 1],
[1, 0, 0, 0, 1, 0, 0, 1, 0, 1],
[1, 0, 0, 0, 1, 0, 0, 1, 0, 1],
[1, 0, 1, 1, 1, 1, 0, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
];

It is also possible to modify the map in real-time: write a character in the boxes you want to swap, then hit Refresh map.

Moving involves adding (or subtracting for backwards movements) to the xy coordinates, using basic trigonometry, but only after checking the validity of the move (i.e. that it will not collide with a wall):


function Camera() {
...

this.move = function(distance) {
// return whether valid move or not
x = this.x + Math.cos(this.theta) * distance;
y = this.y + Math.sin(this.theta) * distance;
if (isValidPos(x, y)) {
this.x = x;
this.y = y;
return true;
}
return false;
};
}

function moveUp() {
readMapFromSheet(sheet); // Retrieve the map from the sheet
var camera = new Camera();
camera.readFromSheet(sheet); // Retrieve the camera state from the sheet
camera.move(0.5);
raycast(camera);
}

Turning left (respectively right) is even simpler, adding (respectively subtracting) small constants to the camera angle (mod 2 PI):


function Camera() {
...

this.rotate = function(alpha) {
this.theta = (this.theta + alpha + 2 * Math.PI) % (2 * Math.PI);
};
}

function lookRight() {
readMapFromSheet(sheet);
var camera = new Camera();
camera.readFromSheet(sheet);
camera.rotate(-0.25);
raycast(camera);
}

Actual actions (moving/turning) are shown in a menu:


spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var subMenus = [
{name:"Reset",functionName:"onOpen"},
{name:"Refresh map",functionName:"refresh"},
{name:"Move forward",functionName:"up"},
{name:"Look left",functionName:"left"},
{name:"Look right",functionName:"right"},
{name:"Move backward",functionName:"down"},
{name:"Turn around",functionName:"turn"},
];
spreadsheet.addMenu("Sheetcaster", subMenus);

The ray is cast as follows:

  • Its origin is the cameras 2D coordinates in the map plane
  • Its direction is calculated off the cameras and the column index (the center column will have the exact same direction as the camera; the other columns directions depend on the field of view parameter)


/*
* Given a value on the x axis (screen column),
* return the ray that will be cast
*/
function getRay(camera, x) {
var cos = Math.cos(camera.theta);
var sin = Math.sin(camera.theta);

// from -1 to 1: 0 being when x is the middle column
var k = ((SIZE_X / 2) - x) / SIZE_X;

return new Vector_(
cos / 2 - k * sin * K_FOV,
sin / 2 + k * cos * K_FOV
);
}

Moving the ray is the most involved step:

  • Calculate the distance to the next vertical and horizontal borders
  • Move to the closest border


while (!hit) {
// Next potential wall is on the x axis
if (dist.x < dist.y) {
// Distance from the camera, delta:
/ Distance between each horizontal wall along the ray
dist.x += delta.x;
// step.x is either 1 or -1, depending on the ray direction
mapCoord.x += step.x;
hit = readMap_(mapCoord.x, mapCoord.y);
} else { // Next potential wall is on the y axis
dist.y += delta.y;
mapCoord.y += step.y;
hit = readMap_(mapCoord.x, mapCoord.y);
}
}

The height of the drawn column is nothing fancy: the further the wall, the smaller-looking the wall, hence the smaller the height of the column.

Again, nothing really complicated. However, the simplicity of this wall-height technique is the reason behind its major caveat: there is no clean way to look up or down: you can only turn left or right, and move forward or backward.

Displaying the rendered image is done using a spreadsheet. Each cell becomes a small square pixel, its color being the background color of the cell. We pass our scren buffer matrix to the handy setBackgroundColors:


sheet.getRange(1, 1, SIZE_Y, SIZE_X).setBackgroundColors(screen);

As you probably noticed, the low display density makes the sharp, jagged, edges really visible. Fear not, reader, for we also implemented anti-aliasing!

The anti-aliasing algorithm is even simpler:

  1. Accumulate the length of runs (successions of same-sized columns)
  2. Draw a gradient, from the background (wall and floor) to the wall, above (and below) the columns

When the runs are really small (< 5 columns), we attenuate the gradient intensity, as it would only add another pixel above (below) the column, thus rendering the antialiasing utterly useless.

Real-time was not an objective, the main problem being controlling the player/camera. Scripted movements should however be quite easy to implement with a fixed duration loop, restarting itself using an Apps Script recurrent time-driven trigger (a minute-long loop, repeated every minute). This is left as an exercise to the reader.

Please feel free to copy the script and walk around this Apps Script virtual world.


Thomas Coudray

Thomas is interested in low level computing and application security.                               


Amaury de la Vieuville

Amaury is passionate about algorithmic problem-solving and software engineering.


Ahmed Bougacha

Ahmed is interested in kernels, compilers and theoretical computer science.                               

Read more »

Improving the Apps Marketplace Sign in experience

Easy access and single sign-on to applications has been a cornerstone of the Apps Marketplace since it launched. When a user clicks on an app in the Google Apps universal navigation (the “more” menu), they’re immediately signed into the app resulting in the same experience as when switching between Gmail, Calendar, and other Google apps. However, sometimes users navigate directly to the homepage of the app and want to sign in there. Handling this case while still maintaining a great user experience can be challenging.

To help, we suggest that Marketplace vendors evaluate the Google Identity Toolkit (GITKit). The toolkit drastically improves the sign-in experience for Google Apps users, as well as for users of popular free webmail services such as Gmail, Yahoo! Mail, Hotmail, and AOL Mail.

The biggest improvement in the sign-in flow is that after a user has logged into your website once, their return experience will be as simple as seeing the account (or accounts) they have used with your site and clicking the one they want to use.

For example, the user Bonnie might use the sassyapp.com app for both her main job, as well as for a small business she runs with her husband Clyde. Whenever Bonnie or Clyde need to sign in to sassyapp.com, they simply click the account they want to use.


If the user does not see their account listed, then they go through a one-time flow to add the account which sends them to the screen below. A Google Apps user can either click the Gmail button or type their email address. For users who cannot login with an identity provider, they will be asked to either enter their password or create a new account after entering their email address.



This user experience is based on an industry technique called an account chooser. In fact, Google is in the process of replacing its own login box with an account chooser and you can opt-in to start using it on Google yourself.

The Google Identity Toolkit (GITkit) can be used by any website, but is particularly useful for Apps Marketplace vendors. The toolkit is an external REST-based API built on the exact same infrastructure that Google uses to be a relying party, and includes a JavaScript widget for the same account chooser experience that you can opt-in to use on Google.

For more information, refer to the GITkit and Apps Marketplace documentation.

Eric Sachs

Eric is a Product Manager for Google Security and board member of The OpenID Foundation. He has more than 15 years of experience in the areas of user identity and security for hosted Web applications. During his five-plus years at Google, he has worked as a Product Manager for many services, including the Google Account login system, Google Apps for Your Domain, orkut.com social network, Google Health, Google Security, and Internal Systems.

Read more »

Upload all file types to any Google Account

Over the next few days we will be rolling out an expansion to the feature set of the Google Documents List API. Third-party applications may now upload files of any type to any Google Account. Previously, this was only possible for Google Apps for Business users.

This feature allows developers to roll out their solutions to all Google Docs users. For instance, it’s now possible for developers to build applications that allow all users to back up files from their local hard drive to the cloud. There are a variety of other possible uses for this feature, and some examples include revision control and file distribution. Third-party applications (such as those on the Google Apps Marketplace) can also now use Google Docs as the primary place to store their data without the hassle of creating different solutions for customers of Google Apps for Business versus the free edition of Google Apps.

After they are uploaded, files are available in the Google Docs interface:


To enable uploads for all file types, developers must use the resumable upload feature of the API, and also pass in the ?convert=false URL parameter.

We have also added checksums to all files that are not converted to a native Google Docs format. This means that if you upload a file type we cant convert, or if you choose not to convert a file to a native format, a checksum is now available to help guarantee the integrity of the file between storage and retrieval.

We are also in the process of adding checksums to all previously uploaded unconverted files. Due to the popularity of uploading unconverted files, processing this backlog will take some time to complete.

We’ve recently made a lot of improvements to the documentation that should make implementing all of this easier. For further help, please have a look in the forum.

Want to weigh in on this topic? Discuss on Buzz

Read more »

A One Two Punch for Getting Even More out of Google Apps APIs

Editor’s Note: Guest author Steve Ziegler is a senior architect at BetterCloud—Arun Nagarajan

FlashPanel, a leading enterprise-grade security and management application for Google Apps, makes use of many Google Apps APIs. Each API comes with its own set of rate-limiting quotas, network traffic behavior and response conditions. The challenge we face is to provide our customers with a stable, consistent experience despite these API behavior differences. Fortunately, Google has provided two simple, yet powerful tools to greatly increase our success rate and reliability.

Controlling Throttle Rates with Guava’s RateLimiter


Google Apps APIs operate with quota rates per second or per day. As such, the FlashPanel development team’s objective is to minimize total operation time of a parallelized set of API-intensive processes while avoiding running into Google’s API quota limits. To accomplish this, we can very easily set up a thread-safe RateLimiter for a specific rate per second for each rate restricted API:

final RateLimiter driveApiRateLimiter = RateLimiter.create(QUOTA_RATE_PER_SECOND);

The Guava RateLimiter allows us to attempt to acquire a permit based on the configured rate per second, block until available, and then take it when available, allowing execution.

To use it within the context of a method, we simply reference the rate limiter before making the API call:

public Result performDriveApiCall(driveApiRateLimiter, otherParams){
driveApiRateLimiter.acquire(); // blocks according to rate
// make API call...
}
This provides us with a very easy solution for rate limiting parallelized calls to the same APIs.

Reducing Impact of Network Traffic Issues Through Configured Backoffs


Occasionally, we experience additional network traffic issues despite enforcing rate limits. Google suggests that API clients use an exponential backoff strategy to handle this variety of error response. Typically this category of network issue resolves itself on its own after fractions of a second, but occasionally more time is needed. All we need to do to receive a successful API response is to simply retry the call some number of times, with the interval of time between retries growing exponentially.

Again, Google has made this easy through the Google HTTP Client for Java library’s ExponentialBackOff builder. This class allows us to configure the initial retry time interval, the exponential multiplier, the maximum total time to attempt to retry, and the maximum total time between retries. For example, we could configure a retry to span five minutes, growing with a factor of two, starting at a one second interval, and growing up to a maximum of one minute between retries. An API call with this configuration would retry with the following pattern in terms of seconds between retries:

1, 2, 4, 8, 16, 32, 60, 60, 60

If after this last retry, the API call still was not successful, the failed http response is returned. The code to configure such a strategy using the ExponentialBackOff.Builder reads as follows:

ExponentialBackOff backoff = new ExponentialBackOff.Builder()
.setInitialIntervalMillis(ONE_SECOND)
.setMultiplier(2.0)
.setMaxIntervalMillis(ONE_MINUTE)
.setMaxElapsedTimeMillis(FIVE_MINUTES)
.build();

One potential “gotcha” that we’ve seen is if we accidentally slam a particular API with many simultaneous API calls. In this event, not only would each of these API calls fail, but they would also schedule their retry strategy to occur simultaneously. All subsequent retries would end up firing simultaneously, causing the API calls to continue to fail due to excess per second volumes. The ExponentialBackoff class accounts for this by including a randomization factor within our retry logic that allows us to have each simultaneous API call stagger at different intervals.

For example, using our previous backoff but now with randomization, one API call may retry with these intervals:

1.04, 1.9, 4.23, 7.8, etc.

While a second API call would retry with something like these intervals:

.98, 2.04, 4.1, 8.15, etc.

With this randomization, we avoid API call sequencing collision, mitigating our chances of encountering quota related errors. To simply add this type of randomization, we append to our builder:

builder.setRandomizationFactor(RANDOMIZATION_FACTOR);

Once we have our exponential backoff strategy configured, the Google HTTP Client for Java library allows us to instantiate and assign an HttpBackOffUnsuccessfulResponseHandler to an HttpRequest as part of the request’s initialization:

private HttpBackOffUnsuccessfulResponseHandler handler = new HttpBackOffUnsuccessfulResponseHandler(backoff);

public void initialize(HttpRequest request){
request.setUnsuccessfulResponseHandler(handler);
}

Final Thoughts


By restricting our API calls using Google Guava’s easy-to-use RateLimiter, and by employing an exponential backoff strategy using the Google HTTP Client for Java library’s ExponentialBackOff, we are able to significantly reduce the amount of network traffic errors received by our Google Apps API calls, improving FlashPanel’s reliability and the overall user experience.

Steve is Senior Architect at BetterCloud, the makers of FlashPanel, the number one security and management application for Google Apps. Follow BetterCloud on Google+ at plus.google.com/+Bettercloud.

Posted by Greg Knoke, Googler
Read more »

Using Google Document List APIs to build Memeo Connect for Google Docs


Building Memeo Connect for Google Docs

Editors Note: This post was written by our partner Memeo, a digital media management company. Memeo Connect™ for Google Docs enhances Google Docs capabilities. We invited Memeo to share their experiences building an application on top of Google Apps utilizing some of our APIs. Other partners will share their experiences in future posts. 

Hi Im Matthew Tonkin, Mac Applications Architect at Memeo.  Google has been a great partner in helping us bring Memeo Connect to market.  Were excited about the new additions to the Google Documents List APIs and the products weve been working on for them.

Google Apps  is a great way for businesses to share and collaborate on documents, but more importantly, it has allowed businesses to move much of their office and IT infrastructure online for dramatic operating cost reductions.  Until recently, Google Docs users had no way of uploading, storing, syncing and sharing files of any type.  The big news is that Google Docs now supports all file types and there are Documents List APIs to prove it.  January saw the release of the updated Documents List API with this new arbitrary file support, but no desktop client software to manage file syncing between the desktop and the cloud.  Memeo Connect for Google Apps is that missing link.  Memeo set out to bridge Google Docs cloud storage with desktop software.  A simple goal that has big implications for where users store documents and how they are shared.  

The end result is a desktop application that is fully supported by Google Docs for online storage, synchronization, sharing and data management. With Memeo Connect, instant access to your important documents while online or offline is now very possible. Memeo Connect is available on both Windows and Mac platforms.







Our timeline for Memeo Connect was impossibly short due to Google’s aggressive timeline for launch. How did we do it?  Apart from the obvious late nights, junk food and beer, we received help from Google to take this product from concept to reality.  Some of it came in the form of new APIs, some directly from the Documents List API team, some from the client libraries and some from the discussion groups.



1. Keeping native file formats

Google Docs now supports keeping files in their native format.  Previously Microsoft Office files and images were converted to the online Google Document formats, removing much of the application specific formatting options used in the Office file formats.  However, its now possible to upload Microsoft Office files and images without conversion, meaning users can keep all of their custom file formatting.

You can get all of this with a simple parameter in the post URL when uploading the new document.

Google Documents List API

https://docs.google.com/feeds/default/private/full?convert=false










If like us, you use the client libraries, then its just as easy.

Google Data Objective-C client library**

NSURL *uploadURL = [[mDocListFeed postLink] URL];
GDataQueryDocs *uploadQuery = [GDataQueryDocs queryWithFeedURL:uploadURL];
[uploadQuery setShouldConvertUpload:NO];


Google Data .NET client library

string uploadURL = DocumentsListQuery.documentsBaseUri + "?convert=false";
docService.StreamSend(new Uri(uploadURL), fileStreamHandle, GDataRequestType.Insert, contentType, docTitle); 


The new features dont just handle Microsoft Office files.  Any file type is supported with no additional parameters or changes to client code, however the support for these features is only available through the Google Documents List API for users that have a Premier account.



2. Bigger file size limits and resumable uploads

Google Docs now supports file uploads up to 1GB and is resumable, so failed or paused uploads can pick up where they left off.

Google Documents List API
http://code.google.com/apis/documents/docs/3.0/developers_guide_protocol.html#ResumableUpload


Resumable post link:

resumable-create-media" type="application/atom+xml"
    href="https://docs.google.com/feeds/upload/create-session/default/private/full"/>


Request:

POST /feeds/upload/create-session/default/private/full HTTP/1.1
Host: docs.google.com
GData-Version: 3.0
Authorization:
Content-Length: 0
Content-Type: application/pdf
Slug: MyTitle
X-Upload-Content-Type: application/pdf
X-Upload-Content-Length: 1234567



Resuming:

POST HTTP/1.1
Host: docs.google.com
Content-Length: 100000
Content-Type: application/pdf
Content-Range: bytes 0-99999/1234567



Google Data Objective-C client library**

Resumable uploads are automatically enabled when switching to the uploadLink URL

NSURL *uploadURL = [[mDocListFeed uploadLink] URL];
GDataQueryDocs * uploadQuery = [GDataQueryDocs queryWithFeedURL:uploadURL];

Pausing and resuming uploads is also made easy.

[mUploadTicket pauseUpload];
[mUploadTicket resumeUpload];

Google Data .NET client library

ResumableUploader resumableUploader = new ResumableUploader();
if (newFile)
    resumableUploader.Insert(authentication, docEntry);
else if (partialFile)
    resumableUploader.Resume(authentication, resumeUri, httpMethod, fileStream, cotentType);
else if (updateExistingFile)
    resumableUploader.Update(authentication, docEntry);

** Objective-C code samples have been taken from the Docs Sample code



3. Client Libraries for Mac & Windows

The Google Documents List API provides all of the backend server functionality but isnt ideal for rapid client application development.  As client developers, we prefer the efficiencies provided by a wrapper in our native client languages.  This is where the client libraries for Objective-C and .NET allowed us to shorten our application development time significantly.  Without the client libraries, we simply would not have been able to achieve our goals for Memeo Connect in the time we had available.

Many of the Documents List API features we worked with in our early development were not available through the client libraries.  This was initially quite daunting because of the risk that we would have to drop down to raw server calls and miss out on the efficiencies we gained through using the client libraries.  However as we got to know the client libraries better, we found they were written flexibly enough that we never had to do that - there was always a way to bend them enough to get what we needed.  A sign of great design by their architects.

For example uploading without conversion was simple in the Objective-C client library even before it was officially updated to support it.

NSURL *uploadURL = [[mDocListFeed postLink] URL];
GDataQueryDocs *uploadQuery = [GDataQueryDocs queryWithFeedURL:uploadURL];
[uploadQuery addCustomParameterWithName:@"convert" value:@"false"];



4. Support from Google

The Documents List API team were of enormous help throughout the course of this project.  As with most of Googles public APIs, theres always an avenue to ask questions about how to best use the technology, pursue bugs or request new features.  The new Google Apps Discussion Groups are simply the best way to get an answer quickly and is invaluable in getting past whatever is blocking your progress. Google Developer Relations people monitor the discussion groups and frequently answer questions, link to other relevant resources, and provide code samples.


Whats next?

We had a sizable list of things we really wanted to do with Memeo Connect 1.0 and some of that had to wait for 1.x or 2.0.  Were looking forward to continuing to work with Google and file as many feature requests as we can to make some of these new features a reality.  Anyone can file a feature request for Google Apps APIs and I can assure you they all get considered.

In future releases well be adding more support for direct file system integration, better tools to manage sharing and were really excited about supporting new devices.  Get ready to see more Google Docs in more places.
Read more »