Project Strobe was started to help users have control over their data while giving developers more explicit rules of the road to ensure everyone is confident that their data is secure. One result of this effort has been to expand our app verification program to cover more apps and more types of data access. It is important to understand how the process works so that you can optimally build your app and streamline the verification process. Here we walk you through the process of preparing your app for OAuth verification.
The first thing you should do is confirm whether your app needs verification. App verification is only required if you want to launch your app widely to consumer or enterprise users and the app requests sensitive or restricted scopes. Apps that use non-sensitive scopes, are under development, or are built just for your own G Suite users are not required to go through verification. If the app is just for users within your own organization, choose the ‘Internal’ application type to restrict the app to use within your own organization and skip verification.
Once you initiate app verification, it is not easy to make updates to your app's Google API configuration. If you make any changes while in the process, you will need to start over again, so it’s critical that you get your app ready before initiating verification to avoid delays.
The first thing you need to do is look at your code on each platform to determine which OAuth scopes (Google APIs) your service needs. Be sure to do this on every client; we often see that apps will request different scopes on different platforms, and then initiate app verification on a subset of scopes than your clients actually use. Often, you can find the scopes by searching your code for the string “www.googleapis.com/auth”. Not all legacy scopes contain that string so you may also want to find the code related to the Google API library you’re using (on the specific platform) to see what scopes are being requested, or look at our directory of scopes.
Once you have identified all of the scopes that your apps use, you can check to see whether they are sensitive or restricted by going to the Cloud Console (APIs & Services -> Credentials -> OAuth consent screen -> Scopes for Google APIs) and pressing the ‘Add scope’ button. This will bring up the following window:
If the scope has a lock icon, it means that the scope is either sensitive or restricted and that you’ll need to go through app verification before you can widely launch to Google users.
[Note that the tool only lists scopes for APIs that you’ve enabled for your project. If you don’t see a scope listed, you’ll first need to enable the corresponding API for your project from the API Library. The fact that you’re not seeing the scope used in your code may mean that you have clients set up in different projects.]
Apps are reviewed and approved at the project level so you’ll want to make sure that you’ve configured your clients properly before starting app verification. If you have multiple projects, each one will have to independently go through app verification.
When to add multiple clients to a project: You may have multiple clients for your app to support different platforms like Android, Web and iOS. Ideally, all of these clients should be in the same project because it will smooth out the cross-client consent experience. When clients are in the same project, users only need to provide consent to one of the clients. Other clients can automatically get tokens without forcing the user to go through the consent flow for the same requested scopes again. The user is agreeing to share data with your service regardless of which platform they happen to be using and your service terms should be the same across platforms.
When to separate clients into separate projects: Your company may also have multiple apps that you publish to users. You may or may not want to host the clients related to your different apps in the same project. Generally, if the different apps use the same login system, have the same privacy policy and users recognize the brand of the publisher of all the apps, then it makes sense to have all the clients in the same project. For example, if PersonalFinance Corp has accounting, budgeting and tax apps that all share the same login, privacy policy and users recognize the PersonalFinance Corp brand, then it is best to structure those all in the same project. However, if CoolGames publisher has lots of titles that have different login systems and different privacy policies, or users are more familiar with the individual game titles than the CoolGames brand, then you should use separate projects.
Reorganizing projects: It is not possible to move or reorganize clients once they are created. If you want to make changes, you can either choose to create new clients in a centralized project or get each app verified independently. If you create new clients in a centralized project, you’ll update your apps to use the new client and abandon the old clients. The issue you may encounter with this approach is that your app may have to obtain user consent all over again (if the user hasn’t also consented to your other client). Alternately, you can leave your clients in separate projects; however, each project will have to go through app verification independently and users will have to consent to each of your clients individually.
Setting up test vs production projects: For many developers, it is also helpful to have a parallel test project to your production project. This allows you to easily change scopes or other app properties and test behavior without having to go through app verification.
If your app does need to be verified, you’ll want to make sure the information about your project is up-to-date to avoid delay.
As we roll out changes across our API ecosystem, it is important to make sure your projects have up-to-date contact information. We often need to send notifications about changes, and have had developers miss important updates because of incorrect contact information which has resulted in their app being unexpectedly disabled. One way to help ensure your team gets notifications is to create a Google Group that aliases to a stable group within your company (and be sure to configure the group to receive emails from non-members). Another option is to create an Organizational Resource in the Cloud Console so that your client assets can be centrally administered and recovered when owners leave the company. It’s also very good practice to ensure the owners of the Android/iOS/Web clients are also owners or editors of the project. Domain verification is also required for every app, so you will also want to add your DNS administrator to the project so that person can easily go through the process.
To update project owners, use Cloud IAM in the Cloud Console (Cloud Console -> IAM and admin -> IAM).
Branding info includes your app’s name and logo. It is critical that these are accurate because users use these to decide whether they know and trust your app. In the verification process, we will validate that you own the brand and logo and that it matches the information on your web site. If you make changes, your previously approved branding will continue to be shown until the new information can be verified.
You will also need to verify the domain associated with your brand. This is true even if you only have Android/iOS versions of your app because you must have a website to publicly host your privacy policy. You start the domain verification process by linking your domain to your project in the Cloud Console (APIs & Services -> Domain verification). You’ll then need to go to the Search Console to prove that you own and control the domain.
Domain verification is a key security feature for your web clients. If you have web clients in your project, each of those must have their Authorized Redirect URIs or Authorized JavaScript Origins match an already verified domain. This enables us to guarantee that OAuth tokens are only returned to your application.
Since you’ve already identified the scopes that your app uses, you should now check to see if you can change scopes to minimize your data access. Our API User Data Policy requires that you only request information that your app needs and that you’re clear to the user about how you will use it. It’s inappropriate to gain access to Google user data for alternate purposes such as advertising and market research.
In particular, you’ll want to try to avoid the use of restricted scopes. The verification process for restricted scopes can take several weeks longer than sensitive scopes. It also requires significant documentation and may involve a third-party security assessment that you must pay for. Currently, only specific Gmail scopes are restricted, but we have announced that most Drive scopes are also becoming restricted in early 2020.
If your app does need to access a restricted scope, consider architecting your app such that the Google user data is only ever stored client-side on the user’s device (like a contact manager app). Storing data in the cloud or on your own servers will require you to obtain a third-party security assessment (at your expense), and could also result in significant work to resolve any security issues found during the assessment.
Once you’ve decided on the scopes your app will need, make sure that they are registered with your project and reflected in your app’s code. We’ve seen many cases where a developer’s code calls a different set of scopes than those that have been registered in the Cloud Console. If your app does this, your users will see an unverified app error. Many developers request troubleshooting help because their users are unexpectedly seeing these errors even though their app was approved. Inevitably, it is because their code does not match what was verified. Similarly, if you need to add new scopes to your application, you’ll need to get those scopes approved before you launch the functionality into your production app (a test client is going to be essential here).
While you’re thinking about scopes, you should also consider how and when you are asking your users for consent. The best practice is to not request scopes at sign-in, but to use incremental authorization to allow a user to access a particular feature when they want it. This is a great way to build trust because the user interacts in a particular feature, can see the benefit of the feature, and understands why granting a particular permission will make the feature more useful.
Our goal in verifying apps is to ensure that any data users choose to share with third-parties is well-managed and meets users’ expectations about how it will be used. Your privacy policy is your public contract to your users and a critical proof to us that users’ expectations will be met.
You must include a link to your privacy policy on your website. If the domain where you host that policy isn’t verified, we won’t verify your app. If your app is purely mobile, with no server-side component, you will still need a privacy policy, but it may be very simple and describe that your app only stores data on a user’s device.
Google can not provide guidance on your privacy policy, but if your app requests restricted scopes, we will scrutinize your policy to understand how you plan to use that data and ensure that it conforms to our requirements. Make sure you understand the Limited Use requirements, and consult with your legal counsel to ensure that your privacy policy is consistent with the requirements. To ensure clarity in how your app handles email content, we also recommend adding the following statement to your application’s home page: “App’s use of information received from Gmail APIs will adhere to Google's Limited Use Requirements.” This is needed when your privacy policy is not specific in how email content is used.
Once you have your project(s) configured with all the appropriate information, you can submit your app for verification. We have three different types of app verification depending on the scopes you request, each taking a different amount of time to complete. If you start your verification with one set of scopes and later decide you need different scopes, you usually need to finish your existing verification before you can start the process again. This could cause frustration and lengthen your overall verification process.
Brand Verification is our simplest process and validates that your brand name and logo belong to you. It is an optional step if your app is requesting non-sensitive scopes like Google Sign-In and typically takes just 2 to 3 business days. If your app doesn’t go through brand verification, users will only see your domain name listed on the consent page.
Starting in June 2019, we greatly expanded the classification of sensitive scopes and started requiring more extensive verification for new apps that are accessing those scopes. Existing apps that are already accessing sensitive scopes need to go through this verification process in the latter half of 2019.
Sensitive scope verification involves brand and domain validation, checking that the privacy policy is prominently available from your application home page. We also review your app and privacy policy against our API Services: User Data Policy and check for deceptive practices. The privacy policy must disclose the manner in which your application accesses, uses, stores, or shares Google user data. Your use of Google user data must be limited to the practices disclosed in your published privacy policy.
A YouTube or accessible Drive video will also be required to understand how users will experience your request for scopes, showing specifically how they’ll benefit from granting you access. The identity of your app needs to be clear from the video (including the app’s client ID), and you’ll need to highlight the value proposition you communicate to the user before requesting the scopes.
Until verification is completed, users will see an unverified app page when your app requests a scope requiring verification. Up to 100 users may choose to grant access while your app is unverified. After that, users will be blocked from granting access to your app until verification is complete.
Sensitive scope verification usually takes 3 to 5 business days if there aren’t any issues with your app.
Restricted scope verification is a much more involved process. In addition to going through all the steps for a sensitive scope verification, your app will also have a much more rigorous privacy policy review to ensure that your use of Google user data conforms to our Limited Use requirements. Only permitted application types will be considered for access to restricted scopes. Finally, if your app stores data on a server, you will need to pass an annual security assessment.
We do error validation before allowing you to click the ‘Submit for Verification’ button. Here are some common reasons why the button is not clickable:
When you submit your app for verification, you will need to provide a written explanation for why your app needs the requested scopes. This explanation should include the nature of the feature and how the user will benefit from using it. It’s also best to include a link to your YouTube video in the original submission to save some back and forth with the review team.
You’ll also be asked again what email should receive questions and notifications about the verification process. Make sure you provide an address that you pay attention to and can receive emails from outside your domain. Questions will go to the person who initiated verification (not necessarily project owners) and the contact email address provided in the verification form. We’ve seen many requests delayed because the developer hasn’t responded to questions from the verification team.
Apps with sensitive and restricted scopes often need to answer questions from the verification team. If you believe it has taken a long time to get a response from the verification team, you should search your inbox for messages from ‘api-oauth-dev-verification-reply’ to ensure that you haven’t missed anything.
By following these guidelines for submitting your app for verification, you can greatly streamline the process of getting your app approved and released to the Google user community. If you have any follow-up questions, be sure to scan the OAuth API Verification FAQ.
Students and working professionals use Google Docs every day to help enhance their productivity and collaboration. The ability to easily share a document and simultaneously edit it together are some of our users' favorite product features. However, many small businesses, corporations, and educational institutions often find themselves needing to automatically generate a wide variety of documents, ranging from form letters to customer invoices, legal paperwork, news feeds, data processing error logs, and internally-generated documents for the corporate CMS (content management system).
Mail merge is the process of taking a master template document along with a data source and "merging" them together. This process makes multiple copies of the master template file and customizes each copy with corresponding data of distinct records from the source. These copies can then be "mailed," whether by postal service or electronically. Using mail merge to produce these copies at volume without human labor has long been a killer app since word processors and databases were invented, and now, you can do it in the cloud with G Suite APIs!
While the Document Service in Google Apps Script has enabled the creation of Google Docs scripts and Docs Add-ons like GFormit (for Google Forms automation), use of Document Service requires developers to operate within the Apps Script ecosystem, possibly a non-starter for more custom development environments. Programmatic access to Google Docs via an HTTP-based REST API wasn't possible until the launch of the Google Docs API earlier this year. This release has now made building custom mail merge applications easier than ever!
Today's technical overview video walks developers through the concept and flow of mail merge operations using the Docs, Sheets, Drive, and Gmail APIs. Armed with this knowledge, developers can dig deeper and access a fully-working sample application (Python), or just skip it and go straight to its open source repo. We invite you to check out the Docs API documentation as well as the API overview page for more information including Quickstart samples in a variety of languages. We hope these resources enable you to develop your own custom mail merge solution in no time!
Posted by Wesley Chun (@wescpy), Developer Advocate, Google Cloud
Google Cloud Platform (GCP) provides infrastructure, serverless products, and APIs that help you build, innovate, and scale. G Suite provides a collection of productivity tools, developer APIs, extensibility frameworks and low-code platforms that let you integrate with G Suite applications, data, and users. While each solution is compelling on its own, users can get more power and flexibility by leveraging both together.
In the latest episode of the G Suite Dev Show, I'll show you one example of how you can take advantage of powerful GCP tools right from G Suite applications. BigQuery, for example, can help you surface valuable insight from massive amounts of data. However, regardless of "the tech" you use, you still have to justify and present your findings to management, right? You've already completed the big data analysis part, so why not go that final mile and tap into G Suite for its strengths? In the sample app covered in the video, we show you how to go from big data analysis all the way to an "exec-ready" presentation.
The sample application is meant to give you an idea of what's possible. While the video walks through the code a bit more, let's give all of you a high-level overview here. Google Apps Script is a G Suite serverless development platform that provides straightforward access to G Suite APIs as well as some GCP tools such as BigQuery. The first part of our app, the runQuery() function, issues a query to BigQuery from Apps Script then connects to Google Sheets to store the results into a new Sheet (note we left out CONSTANT variable definitions for brevity):
runQuery()
CONSTANT
function runQuery() { // make BigQuery request var request = {query: BQ_QUERY}; var queryResults = BigQuery.Jobs.query(request, PROJECT_ID); var jobId = queryResults.jobReference.jobId; queryResults = BigQuery.Jobs.getQueryResults(PROJECT_ID, jobId); var rows = queryResults.rows; // put results into a 2D array var data = new Array(rows.length); for (var i = 0; i < rows.length; i++) { var cols = rows[i].f; data[i] = new Array(cols.length); for (var j = 0; j < cols.length; j++) { data[i][j] = cols[j].v; } } // put array data into new Sheet var spreadsheet = SpreadsheetApp.create(QUERY_NAME); var sheet = spreadsheet.getActiveSheet(); var headers = queryResults.schema.fields; sheet.appendRow(headers); // header row sheet.getRange(START_ROW, START_COL, rows.length, headers.length).setValues(data); // return Sheet object for later use return spreadsheet; }
It returns a handle to the new Google Sheet which we can then pass on to the next component: using Google Sheets to generate a Chart from the BigQuery data. Again leaving out the CONSTANTs, we have the 2nd part of our app, the createColumnChart() function:
CONSTANTs
createColumnChart()
function createColumnChart(spreadsheet) { // create & put chart on 1st Sheet var sheet = spreadsheet.getSheets()[0]; var chart = sheet.newChart() .setChartType(Charts.ChartType.COLUMN) .addRange(sheet.getRange(START_CELL + ':' + END_CELL)) .setPosition(START_ROW, START_COL, OFFSET, OFFSET) .build(); sheet.insertChart(chart); // return Chart object for later use return chart; }
The chart is returned by createColumnChart() so we can use that plus the Sheets object to build the desired slide presentation from Apps Script with Google Slides in the 3rd part of our app, the createSlidePresentation() function:
createSlidePresentation()
function createSlidePresentation(spreadsheet, chart) { // create new deck & add title+subtitle var deck = SlidesApp.create(QUERY_NAME); var [title, subtitle] = deck.getSlides()[0].getPageElements(); title.asShape().getText().setText(QUERY_NAME); subtitle.asShape().getText().setText('via GCP and G Suite APIs:\n' + 'Google Apps Script, BigQuery, Sheets, Slides'); // add new slide and insert empty table var tableSlide = deck.appendSlide(SlidesApp.PredefinedLayout.BLANK); var sheetValues = spreadsheet.getSheets()[0].getRange( START_CELL + ':' + END_CELL).getValues(); var table = tableSlide.insertTable(sheetValues.length, sheetValues[0].length); // populate table with data in Sheets for (var i = 0; i < sheetValues.length; i++) { for (var j = 0; j < sheetValues[0].length; j++) { table.getCell(i, j).getText().setText(String(sheetValues[i][j])); } } // add new slide and add Sheets chart to it var chartSlide = deck.appendSlide(SlidesApp.PredefinedLayout.BLANK); chartSlide.insertSheetsChart(chart); // return Presentation object for later use return deck; }
Finally, we need a driver application that calls all three one after another, the createColumnChart() function:
function createBigQueryPresentation() { var spreadsheet = runQuery(); var chart = createColumnChart(spreadsheet); var deck = createSlidePresentation(spreadsheet, chart); }
We left out some detail in the code above but hope this pseudocode helps kickstart your own project. Seeking a guided tutorial to building this app one step-at-a-time? Do our codelab at g.co/codelabs/bigquery-sheets-slides. Alternatively, go see all the code by hitting our GitHub repo at github.com/googlecodelabs/bigquery-sheets-slides. After executing the app successfully, you'll see the fruits of your big data analysis captured in a presentable way in a Google Slides deck:
This isn't the end of the story as this is just one example of how you can leverage both platforms from Google Cloud. In fact, this was one of two sample apps featured in our Cloud NEXT '18 session this summer exploring interoperability between GCP & G Suite which you can watch here:
Stay tuned as more examples are coming. We hope these videos plus the codelab inspire you to build on your own ideas.
Google Cloud Next '18 is only a few days away, and this year, there are over 500 sessions covering all aspects of cloud computing, from G Suite to the Google Cloud Platform. This is your chance to learn first-hand how to build custom solutions in G Suite alongside other developers from Independent Software Vendors (ISVs), systems integrators (SIs), and industry enterprises.
G Suite's intelligent productivity apps are secure, smart, and simple to use, so why not integrate your apps with them? If you're planning to attend the event and are wondering which sessions you should check out, here are some sessions to consider:
I look forward to meeting you in person at Next '18. In the meantime, check out the entire session schedule to find out everything it has to offer. Don't forget to swing by our "Meet the Experts" office hours (Tue-Thu), G Suite "Collaboration & Productivity" showcase demos (Tue-Thu), the G Suite Birds-of-a-Feather meetup (Wed), and the Google Apps Script & G Suite Add-ons meetup (just after the BoF on Wed). I'm excited at how we can use "all the tech" to change the world. See you soon!
Posted by Wesley Chun (@wescpy), Developer Advocate, G Suite
While most chatbots respond to user requests in a synchronous way, there are scenarios when bots don't perform actions based on an explicit user request, such as for alerts or notifications. In today's DevByte video, I'm going to show you how to send messages asynchronously to rooms or direct messages (DMs) in Hangouts Chat, the team collaboration and communication tool in G Suite.
What comes to mind when you think of a bot in a chat room? Perhaps a user wants the last quarter's European sales numbers, or maybe, they want to look up local weather or the next movie showtime. Assuming there's a bot for whatever the request is, a user will either send a direct message (DM) to that bot or @mention the bot from within a chat room. The bot then fields the request (sent to it by the Hangouts Chat service), performs any necessary magic, and responds back to the user in that "space," the generic nomenclature for a room or DM.
Our previous DevByte video for the Hangouts Chat bot framework shows developers what bots and the framework are all about as well as how to build one of these types of bots, in both Python and JavaScript. However, recognize that these bots are responding synchronously to a user request. This doesn't suffice when users want to be notified when a long-running background job has completed, when a late bus or train will be arriving soon, or when one of their servers has just gone down. Recognize that such alerts can come from a bot but also perhaps a monitoring application. In the latest episode of the G Suite Dev Show, learn how to integrate this functionality in either type of application.
From the video, you can see that alerts and notifications are "out-of-band" messages, meaning they can come in at any time. The Hangouts Chat bot framework provides several ways to send asynchronous messages to a room or DM, generically referred to as a "space." The first is the HTTP-based REST API. The other way is using what are known as "incoming webhooks."
The REST API is used by bots to send messages into a space. Since a bot will never be a human user, a Google service account is required. Once you create a service account for your Hangouts Chat bot in the developers console, you can download its credentials needed to communicate with the API. Below is a short Python sample snippet that uses the API to send a message asynchronously to a space.
from apiclient import discovery from httplib2 import Http from oauth2client.service_account import ServiceAccountCredentials SCOPES = 'https://www.googleapis.com/auth/chat.bot' creds = ServiceAccountCredentials.from_json_keyfile_name( 'svc_acct.json', SCOPES) CHAT = discovery.build('chat', 'v1', http=creds.authorize(Http())) room = 'spaces/<ROOM-or-DM>' message = {'text': 'Hello world!'} CHAT.spaces().messages().create(parent=room, body=message).execute()
The alternative to using the API with service accounts is the concept of incoming webhooks. Webhooks are a quick and easy way to send messages into any room or DM without configuring a full bot, i.e., monitoring apps. Webhooks also allow you to integrate your custom workflows, such as when a new customer is added to the corporate CRM (customer relationship management system), as well as others mentioned above. Below is a Python snippet that uses an incoming webhook to communicate into a space asynchronously.
import requests import json URL = 'https://chat.googleapis.com/...&thread_key=T12345' message = {'text': 'Hello world!'} requests.post(URL, data=json.dumps(message))
Since incoming webhooks are merely endpoints you HTTP POST to, you can even use curl to send a message to a Hangouts Chat space from the command-line:
curl
curl \ -X POST \ -H 'Content-Type: application/json' \ 'https://chat.googleapis.com/...&thread_key=T12345' \ -d '{"text": "Hello!"}'
To get started, take a look at the Hangouts Chat developer documentation, especially the specific pages linked to above. We hope this video helps you take your bot development skills to the next level by showing you how to send messages to the Hangouts Chat service asynchronously.
We recently introduced Hangouts Chat to general availability. This next-generation messaging platform gives G Suite users a new place to communicate and to collaborate in teams. It features archive & search, tighter G Suite integration, and the ability to create separate, threaded chat rooms. The key new feature for developers is a bot framework and API. Whether it's to automate common tasks, query for information, or perform other heavy-lifting, bots can really transform the way we work.
In addition to plain text replies, Hangouts Chat can also display bot responses with richer user interfaces (UIs) called cards which can render header information, structured data, images, links, buttons, etc. Furthermore, users can interact with these components, potentially updating the displayed information. In this latest episode of the G Suite Dev Show, developers learn how to create a bot that features an updating interactive card.
As you can see in the video, the most important thing when bots receive a message is to determine the event type and take the appropriate action. For example, a bot will perform any desired "paperwork" when it is added to or removed from a room or direct message (DM), generically referred to as a "space" in the vernacular.
Receiving an ordinary message sent by users is the most likely scenario; most bots do "their thing" here in serving the request. The last event type occurs when a user clicks on an interactive card. Similar to receiving a standard message, a bot performs its requisite work, including possibly updating the card itself. Below is some pseudocode summarizing these four event types and represents what a bot would likely do depending on the event type:
function processEvent(req, rsp) { var event = req.body; // event type received var message; // JSON response message if (event.type == 'REMOVED_FROM_SPACE') { // no response as bot removed from room return; } else if (event.type == 'ADDED_TO_SPACE') { // bot added to room; send welcome message message = {text: 'Thanks for adding me!'}; } else if (event.type == 'MESSAGE') { // message received during normal operation message = responseForMsg(event.message.text); } else if (event.type == 'CARD_CLICKED') { // user-click on card UI var action = event.action; message = responseForClick( action.actionMethodName, action.parameters); } rsp.send(message); };
The bot pseudocode as well as the bot featured in the video respond synchronously. Bots performing more time-consuming operations or those issuing out-of-band notifications, can send messages to spaces in an asynchronous way. This includes messages such as job-completed notifications, alerts if a server goes down, and pings to the Sales team when a new lead is added to the CRM (Customer Relationship Management) system.
Hangouts Chat supports more than JavaScript or Python and Google Apps Script or Google App Engine. While using JavaScript running on Apps Script is one of the quickest and simplest ways to get a bot online within your organization, it can easily be ported to Node.js for a wider variety of hosting options. Similarly, App Engine allows for more scalability and supports additional languages (Java, PHP, Go, and more) beyond Python. The bot can also be ported to Flask for more hosting options. One key takeaway is the flexibility of the platform: developers can use any language, any stack, or any cloud to create and host their bot implementations. Bots only need to be able to accept HTTP POST requests coming from the Hangouts Chat service to function.
At Google I/O 2018 last week, the Hangouts Chat team leads and I delivered a longer, higher-level overview of the bot framework. This comprehensive tour of the framework includes numerous live demos of sample bots as well as in a variety of languages and platforms. Check out our ~40-minute session below.
To help you get started, check out the bot framework launch post. Also take a look at this post for a deeper dive into the Python App Engine version of the vote bot featured in the video. To learn more about developing bots for Hangouts Chat, review the concepts guides as well as the "how to" for creating bots. You can build bots for your organization, your customers, or for the world. We look forward to all the exciting bots you're going to build!
We recently introduced Google Slides Add-ons so developers can add functionality from their apps to ours. Here are examples of Slides Add-ons that some of our partners have already built—remember, you can also add functionality to other apps outside of Slides, like Docs, Sheets, Gmail and more.
When it comes to Slides, if your users are delivering a presentation or watching one, sometimes it's good to know how far along you are in the deck. Wouldn't it be great if Slides featured progress bars?
In the latest episode of the G Suite Dev Show, G Suite engineer Grant Timmerman and I show you how to do exactly that—implement simple progress bars using a Slides Add-on.
Using Google Apps Script, we craft this add-on which lets users turn on or hide progress bars in their presentations. The progress bars are represented as appropriately-sized rectangles at the bottom of slide pages. Here's a snippet of code for createBars(), which adds the rectangle for each slide.
createBars()
var BAR_ID = 'PROGRESS_BAR_ID'; var BAR_HEIGHT = 10; // px var presentation = SlidesApp.getActivePresentation(); function createBars() { var slides = presentation.getSlides(); deleteBars(); for (var i = 0; i < slides.length; ++i) { var ratioComplete = (i / (slides.length - 1)); var x = 0; var y = presentation.getPageHeight() - BAR_HEIGHT; var barWidth = presentation.getPageWidth() * ratioComplete; if (barWidth > 0) { var bar = slides[i].insertShape(SlidesApp.ShapeType.RECTANGLE, x, y, barWidth, BAR_HEIGHT); bar.getBorder().setTransparent(); bar.setLinkUrl(BAR_ID); } } }
To learn more about this sample and see all of the code, check out the Google Slides Add-on Quickstart. This is just one example of what you can build using Apps Script and add-ons; here's another example where you can create a slide presentation from a collection of images using a Slides Add-on.
If you want to learn more about Apps Script, check out the video library or view more examples of programmatically accessing Google Slides here. To learn about using Apps Script to create other add-ons, check out this page in the docs.
You might have seen that we announced new features in G Suite to help teams transform how they work, including Hangouts Chat, a new messaging platform for enterprise collaboration on web and mobile. Perhaps more interesting is that starting today you'll be able to craft your own bot integrations using the Hangouts Chat developer platform and API.
Now, you can create bots to streamline work—automate manual tasks or give your users new ways to connect with your application, all with commands issued from chat rooms or direct messages (DMs). Here are some ideas you might consider:
For example, a bot can take a location from a user, look it up using the Google Maps API, and display the resulting map right within the same message thread in Hangouts Chat. The bot output you see in the image below is generated from the Apps Script bot integration. It returns the JSON payload just below the same image shown on this page in the documentation.
When messages are sent to an Apps Script bot, the onMessage() function is called and passed an event object. The code below extracts the bot name as well as the location requested by the user. The location is then passed to Google Maps to create the static map as well as an openLink URL that takes the user directly to Google Maps if either the map or "Open in Google Maps" link is clicked.
onMessage()
openLink
function onMessage(e) { var bot = e.message.annotations[0].userMention.user.displayName; var loc = encodeURI(e.message.text.substring(bot.length+2)); var mapClick = { "openLink": { "url": "https://google.com/maps/search/?api=1&query=" + loc } }; return { // see JSON payload in the documentation link above }; }
Finally, this function returns everything Hangouts Chat needs to render a UI card assuming the appropriate links, data and Google Maps API key were added to the response JSON payload. It may be surprising, but this is the entire bot and follows this common formula: get the user request, collate the results and respond back to the user.
When results are returned immediately like this, it's known as a synchronous bot. Using the API isn't necessary because you're just responding to the HTTP request. If your bot requires additional processing time or must execute a workflow out-of-band, return immediately then post an asynchronous response when the background jobs have completed with data to return. Learn more about bot implementation, its workflow, as well as synchronous vs. asynchronous responses.
Developers are not constrained to using Apps Script, although it is perhaps one of the easiest ways to create and deploy bots. Overall, you can write and host bots on a variety of platforms:
No longer are chat rooms just for conversations. With feature-rich, intelligent bots, users can automate tasks, get critical information or do other heavy-lifting with a simple message. We're excited at the possibilities that await both developers and G Suite users on the new Hangouts Chat platform and API.
Email remains at the heart of how companies operate. That's why earlier this year, we previewed Gmail Add-ons—a way to help businesses speed up workflows. Since then, we've seen partners build awesome applications, and beginning today, we're extending the Gmail add-on preview to include all developers. Now anyone can start building a Gmail add-on.
Gmail Add-ons let you integrate your app into Gmail and extend Gmail to handle quick actions.
They are built using native UI context cards that can include simple text dialogs, images, links, buttons and forms. The add-on appears when relevant, and the user is just a click away from your app's rich and integrated functionality.
Gmail Add-ons are easy to create. You only have to write code once for your add-on to work on both web and mobile, and you can choose from a rich palette of widgets to craft a custom UI. Create an add-on that contextually surfaces cards based on the content of a message. Check out this video to see how we created an add-on to collate email receipts and expedite expense reporting.
Per the video, you can see that there are three components to the app's core functionality. The first component is getContextualAddOn()—this is the entry point for all Gmail Add-ons where data is compiled to build the card and render it within the Gmail UI. Since the add-on is processing expense reports from email receipts in your inbox, the createExpensesCard() parses the relevant data from the message and presents them in a form so your users can confirm or update values before submitting. Finally, submitForm()takes the data and writes a new row in an "expenses" spreadsheet in Google Sheets, which you can edit and tweak, and submit for approval to your boss.
getContextualAddOn()
createExpensesCard()
submitForm()
Check out the documentation to get started with Gmail Add-ons, or if you want to see what it's like to build an add-on, go to the codelab to build ExpenseIt step-by-step. While you can't publish your add-on just yet, you can fill out this form to get notified when publishing is opened. We can't wait to see what Gmail Add-ons you build!
Originally posted by Paul McReynolds, Product Manager (@pauljmcr), Apps Script and Wesley Chun (@wescpy), Developer Advocate, G Suite on the G Suite Developers Blog
Apps Script is just as popular inside Google as it is among external users and developers. In fact, there are more than 70,000 weekly active scripts written by thousands of Googlers. One of our many uses for Apps Script at Google is to automate and monitor our internal issue tracker.
In spring of this year, we migrated our G Suite issue trackers to a new system based on our internal tracker. This carries a lot of benefits, including improving our ability to track how issues reported from outside of Google relate to bugs and features we're working on internally. We also have an internal Apps Script API that talks to our issue tracker, which we can now use to work with issues reported from outside of Google.
As soon as the migration was finished, we put Apps Script to work monitoring…itself. Now we have a script in place that monitors Apps Script issues as they are reported and upvoted on the public tracker. When we see an issue that's having widespread or sudden impact, the script generates an alert that we can then investigate. With the help of our large, active community of developers, and leveraging Apps Script, we're now able to identify and respond to issues more quickly.
There's no substitute for independent monitoring, and our Apps Script-based approach isn't the first or the last line of defense. Instead, this new script helps us catch anything that our monitoring systems miss by listening to what developers are saying on the tracker.
Please help us keep Apps Script humming! When you notice a problem, search the issue tracker for it and file an issue if it's new. Click the star to let us know you're affected and leave a comment with instructions to reproduce, along with any other relevant details. Those instructions and other details help us respond to the issues more effectively, so please be sure to include them.
Happy scripting!
We're constantly working to secure our users and their data. Earlier this year, we detailed some of our latest anti-phishing tools and rolled-out developer-focused updates to our app publishing processes, risk assessment systems, and user-facing consent pages. Most recently, we introduced OAuth apps whitelisting in G Suite to enable admins to choose exactly which third-party apps can access user data.
Over the past few months, we've required that some new web applications go through a verification process prior to launch based upon a dynamic risk assessment.
Today, we're expanding upon that foundation, and introducing additional protections: bolder warnings to inform users about newly created web apps and Apps Scripts that are pending verification. Additionally, the changes we're making will improve the developer experience. In the coming months, we will begin expanding the verification process and the new warnings to existing apps as well.
Beginning today, we're rolling out an "unverified app" screen for newly created web applications and Apps Scripts that require verification. This new screen replaces the "error" page that developers and users of unverified web apps receive today.
The "unverified app" screen precedes the permissions consent screen for the app and lets potential users know that the app has yet to be verified. This will help reduce the risk of user data being phished by bad actors.
This new notice will also help developers test their apps more easily. Since users can choose to acknowledge the 'unverified app' alert, developers can now test their applications without having to go through the OAuth client verification process first (see our earlier post for details).
Developers can follow the steps laid out in this help center article to begin the verification process to remove the interstitial and prepare your app for launch.
We're also extending these same protections to Apps Script. Beginning this week, new Apps Scripts requesting OAuth access to data from consumers or from users in other domains may also see the "unverified app" screen. For more information about how these changes affect Apps Script developers and users, see the verification documentation page.
Apps Script is proactively protecting users from abusive apps in other ways as well. Users will see new cautionary language reminding them to "consider whether you trust" an application before granting OAuth access, as well as a banner identifying web pages and forms created by other users.
In the coming months, we will continue to enhance user protections by extending the verification process beyond newly created apps, to existing apps as well. As a part of this expansion, developers of some current apps may be required to go through the verification flow.
To help ensure a smooth transition, we recommend developers verify that their contact information is up-to-date. In the Google Cloud Console, developers should ensure that the appropriate and monitored accounts are granted either the project owner or billing account admin IAM role. For help with granting IAM roles, see this help center article.
In the API manager, developers should ensure that their OAuth consent screen configuration is accurate and up-to-date. For help with configuring the consent screen, see this help center article.
We're committed to fostering a healthy ecosystem for both users and developers. These new notices will inform users automatically if they may be at risk, enabling them to make informed decisions to keep their information safe, and will make it easier to test and develop apps for developers.
You might be using the Google Calendar API, or alternatively email markup, to insert events into your users' calendars. Thankfully, these tools allow your apps to do this seamlessly and automatically, which saves your users a lot of time. But what happens if plans change? You need your apps to also be able to modify an event.
While email markup does support this update, it's limited in what it can do, so in today's video, we'll show you how to modify events with the Calendar API. We'll also show you how to create repeating events. Check it out:
Imagine a potential customer being interested in your product, so you set up one or two meetings with them. As their interest grows, they request regularly-scheduled syncs as your product makes their short list—your CRM should be able to make these adjustments in your calendar without much work on your part. Similarly, a "dinner with friends" event can go from a "rain check" to a bi-monthly dining experience with friends you've grown closer to. Both of these events can be updated with a JSON request payload like what you see below to adjust the date and make it repeating:
JSON
var TIMEZONE = "America/Los_Angeles"; var EVENT = { "start": {"dateTime": "2017-07-01T19:00:00", "timeZone": TIMEZONE}, "end": {"dateTime": "2017-07-01T22:00:00", "timeZone": TIMEZONE}, "recurrence": ["RRULE:FREQ=MONTHLY;INTERVAL=2;UNTIL=20171231"] };
This event can then be updated with a single call to the Calendar API's events().patch() method, which in Python would look like the following given the request data above, GCAL as the API service endpoint, and a valid EVENT_ID to update:
events().patch()
GCAL
EVENT_ID
GCAL.events().patch(calendarId='primary', eventId=EVENT_ID, sendNotifications=True, body=EVENT).execute()
If you want to dive deeper into the code sample, check out this blog post. Also, if you missed it, check out this video that shows how you can insert events into Google Calendar as well as the official API documentation. Finally, if you have a Google Apps Script app, you can access Google Calendar programmatically with its Calendar service.
We hope you can use this information to enhance your apps to give your users an even better and timely experience.
Enterprises are always looking for ways to operate more efficiently, and equipping developers with the right tools can make a difference. We launched Team Drives this year to bring the best of what users love about Drive to enterprise teams. We also updated the Google Drive API, so that developers can leverage Team Drives in the apps they build.
In this latest G Suite Dev Show video, we cover how you can leverage the functionality of Team Drives in your apps. The good news is you don't have to learn a completely new API—Team Drives features are built into the Drive API so you can build on what you already know. Check it out:
By the end of this video, you'll be familiar with four basic operations to help you build Team Drives functionality right into your apps:
Want to explore the code further? Check out the deep dive blog post. In all, the Drive API can help a variety of developers create solutions that work with both Google Drive and Team Drives. Whether you're an Independent Software Vendor (ISV), System Integrator (SI) or work in IT, there are many ways to use the Drive API to enhance productivity, help your company migrate to G Suite, or build tools to automate workflows.
Team Drives features are available in both Drive API v2 and v3, and more details can be found in the Drive API documentation. We look forward to seeing what you build with Team Drives!
Last week, we took immediate action to protect users from a phishing attack that attempted to abuse the OAuth authorization infrastructure.
Today, we’re supplementing those efforts to help prevent these types of issues in the future. These changes may add some friction and require more time before you are able to publish your web application, so we recommend that you plan your work accordingly.
To further enforce this policy, we are updating our app publishing process, our risk assessment systems, and our user-facing consent page in order to better detect spoofed or misleading application identities. You may see an error message as you’re registering new applications or modifying existing application attributes in the Google API Console, Firebase Console, or Apps Script editor as a result of this change.
Based on this risk assessment, some web applications will require a manual review. Until the review is complete, users will not be able to approve the data permissions, and we will display an error message instead of the permissions consent page. You can request a review during the testing phase in order to open the app to the public. We will try to process those reviews in 3-7 business days. In the future, we will enable review requests during the registration phase as well.
You can continue to use your app for testing purposes before it is approved by logging in with an account registered as an owner/editor of that project in the Google API Console. This will enable you to add additional testers, as well as initiate the review process.
We also recommend developers review our earlier post outlining their responsibilities when requesting access to user data from their applications. Our teams will continue our constant efforts to support a powerful, useful developer ecosystem that keeps users and their data safe.
cell
fields
{ "repeatCell": { "range": { "endRowIndex": 1 }, "cell": { "userEnteredFormat": { "textFormat": { "bold": true } } }, "fields": "userEnteredFormat/textFormat/bold", } }
userEnteredFormat/textFormat/bold
"fields": "userEnteredFormat/textFormat(bold,italic)"
italic
addresses = GMAIL.users().settings().sendAs().list( userId='me' ).execute().get('sendAs')
{ "sendAs": [{ "sendAsEmail": string, "displayName": string, "replyToAddress": string, "signature": string, "isPrimary": boolean, "isDefault": boolean, "treatAsAlias": boolean, "smtpMsa": { "host": string, "port": integer, "username": string, "password": string, "securityMode": string }, "verificationStatus": string }, ...] }
addresses = GMAIL.users().settings().sendAs().list( userId='me', fields='sendAs(sendAsEmail,isPrimary)' ).execute().get('sendAs')
hd and/or login_hint p
hd