Pieter van der Westhuizen

Developing Gmail contextual gadgets

In my last article, we explored How to develop Gmail sidebar gadgets. In today’s article we’ll take a closer look at what is involved in creating a contextual gadget for Gmail. Gmail contextual gadgets are a good way to add additional functionality to Gmail allowing your user to perform tasks right from inside their Gmail session.

Contextual gadget components

A contextual gadget is essentially made up of the following 3 parts:

The Manifest

The manifest file is used to describe the structure and content of an application. The manifest file is the starting point for any contextual Gmail gadget. Our sample contextual gadget will scan the body text of an e-mail for a number of key words and return a search result from the Add-in Express forums and blog posts. Our manifest file for the sample google gadget will look like the following:

<?xml version="1.0" encoding="UTF-8" ?>
<ApplicationManifest xmlns="https://schemas.google.com/ApplicationManifest/2009">
 
  <Name>ADX Answers</Name>
 
  <Description>
    Answers to Add-in Express questions inside your e-mail.    
  </Description>
 
  <Extension id="ADXExtractor" type="contextExtractor">
    <Name>ADX Stuff</Name>
    <Url>google.com:EmailBodyExtractor</Url>
    <Triggers ref="ADXGadget"/>
    <Scope ref="emailBody"/>
    <Container name="mail"/>
  </Extension>
 
  <Extension id="ADXGadget" type="gadget">
    <Name>Add-in Express Gmail contextual gadget</Name>
    <Url>https://www.coalitionsoft.net/context-gadget.xml</Url>
    <Container name="mail"/>
  </Extension>
 
  <Scope id="emailBody">
    <Url>tag:google.com,2010:auth/contextual/extractor/BODY</Url>
    <Reason>
      This application searches the message body of each email for text related to Add-in Express products.
    </Reason>
  </Scope>
 
</ApplicationManifest>

In the manifest file, we specified the name and description of our application. We also created a new extension called ADXExtractor which will extract content from the e-mail message body. This is accomplished by creating a <Extension> element and setting its child <Url> element’s text to google.com:EmailBodyExtractor, the <Scope> element’s ref attribute to emailBody and the <Container> element’s name attribute to mail. Next, we’ll specify another extension, which will be a reference to our gadget spec. All we need to set for the gadget extension is the <Name> element and the <Url>. The gadget should be hosted on a publicly available server. Finally, add a <Scope> element to indicate which part of the e-mail the gadget needs to access. This is also used to show the user information about the gadget when they are installing it, as illustrated below: A <Scope> element indicates which part of the e-mail the google gadget needs to access and show the user information about the gadget.

Extractors

A contextual gadget is triggered based on text matches found in one of the following e-mail fields:

  • From
  • To
  • Subject
  • Email message body

Matching is accomplished using an extractor. You have a choice of building your own extractor or to simply use one of Google’s pre-canned extractors. Google supplies us with 15 extractors out of the box:

ID Description
google.com:EmailAddressExtractor Finds e-mail address in the subject and message body of the e-mail.
google.com:EmailBodyExtractor Retrieves the first 1000 characters from the e-mail body.
google.com:EmailTimeExtractor Retrieves the sent/receive time of the e-mail.
google.com:HelloWorld Finds “Hello World” in the body and subject fields of the e-mail message (Case insensitive)
google.com:HttpLinkExtractor Returns links to HTTP and HTTPS address inside the message subject and body.
google.com:ListExtractor Finds the list ID and unsubscribe link/e-mail address inside the message.
google.com:MessageIDExtractor Returns the Gmail internal message id
google.com:RawSubjectExtractor Returns the e-mail’s subject line. It contains all annotations such as FW: and RE:
google.com:RecipientCCEmailExtractor Returns all the e-mail address inside the CC fields
google.com:RecipientEmailExtractor Returns all e-mail address for the e-mail, including the TO and CC fields.
google.com:RecipientToEmailExtractor Only return e-mail addresses inside the TO field of the e-mail.
google.com:SenderEmailExtractor Returns the sender’s e-mail address. This value is stored in the FROM field of the e-mail.
google.com:SubjectExtractor Returns the subject of the e-mail with all annotations (FW, RE, etc.) removed.
google.com:USPhoneExtractor Returns all US based phone numbers inside the e-mail message. The format for the phone numbers are : ((1) 800 ) 555-1234)
google.com:USStockTicker Matches US stock symbols in the body and subject fields of the e-mail message.

Gadget Spec

The gadget spec is the same type of file we used for creating the sidebar gadget and contains the settings and actual JavaScript, CSS and HTML code that makes up the gadget. The spec consists of a <ModulePrefs> element, which is used to specify the gadget’s settings. With contextual gadgets you should always include the <Require> element to specify that the gadget depends on the google.contentmatch feature. The <Content> element contains the actual Html, CSS and JavaScript for your gadget and its type attribute should always be set to html and its view attribute to card.

Whilst developing your gadget, it is important to include &nogadgetcache=1 flag in your Gmail url e.g.: <https://mail.google.com/mail/u/0/?pli=1&nogadgetcache=1#inbox/14592c25139c6899Google caches gadgets, which makes debugging and testing your gadget near impossible if this flag is not set. Speaking from experience, this is a must have!

The code for our gadget spec follows below:

<?xml version="1.0" encoding="UTF-8"?>
<Module>
  <ModulePrefs title="Add-in Express Answers"
    description="You ask, ADX answers!"
    height="20"
    author="Add-in Express"
    author_email="add-in-express.com"
    author_location="Poland">
    <Require feature="dynamic-height"/>
 
    <Require feature="google.contentmatch">
      <Param name="extractors">
        google.com:EmailBodyExtractor
      </Param>
    </Require>
 
  </ModulePrefs>
 
  <Content type="html" view="card">
    <![CDATA[
      <link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
      <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
      <div id="links" class="list-group">
      </div>
      <script type="text/javascript">       
        matches = google.contentmatch.getContentMatches();        
        var bodyText = matches[0]["email_body"];
        var result1 = /^.*\b(create|build|program|develop|office|add-in|plug in|addon)\b.*$/.test(bodyText);
        var result2 = /^.*\b(handle|trap|intercept|get|newmail)\b.*$/.test(bodyText);
        var result3 = /^.*\b(add|create|build|program|develop|outlook|task pane|region)\b.*$/.test(bodyText);
        var result4 = /^.*\b(add|create|build|program|develop|excel|function)\b.*$/.test(bodyText);
        var result5 = /^.*\b(add|create|build|program|develop|word|button|ribbon|tab)\b.*$/.test(bodyText);
 
        var params = {};
        params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
        if (result1){
          var url = "//www.add-in-express.com/search-addin-json.php?q=create%20build%20program%20develop%20Outlook%20add-in%20plug%20in%20addon";
        } else if (result2) {    
          var url = "//www.add-in-express.com/search-addin-json.php?q=handle%20trap%20intercept%20get%20newmail";
        } else if (result3) {      
          var url = "//www.add-in-express.com/search-addin-json.php?q=add%20create%20build%20program%20develop%20outlook%20task%20pane%20region";
        } else if (result4) {       
          var url = "//www.add-in-express.com/search-addin-json.php?q=add%20create%20build%20program%20develop%20excel%20functions";
        } else if (result5) {       
          var url = "//www.add-in-express.com/search-addin-json.php?q=add%20create%20build%20program%20develop%20word%20button%20ribbon%20tab";
        } 
 
        gadgets.io.makeRequest(url, loadData, params);
        gadgets.window.adjustHeight(400);   
 
        function loadData(obj) {
          var items = obj.data.result;
          for (var i = 0; i < items.length; i++) {
            var item = items[i];
            $("#links").append('<a href="' + item.link + '" target="_blank" class="list-group-item"><h4 class="list-group-item-heading">' + item.title + '</h4><p class="list-group-item-text">' + item.body + '</p></a>');
          }
        }
      </script>
    ]]>
  </Content>
</Module>

In our gadget code above, we first included references to the Bootstrap library’s CSS style sheet – we’ll use Bootstrap to style our user interface components. We have also included a reference to the jQuery library in order to make it easier to manipulate the DOM. Next, we’ve created an empty <div> element, which will contain the search results. We then called the getContentMatches function, in order to get a reference to the message body, using the following code:

matches = google.contentmatch.getContentMatches();

Using a number of regular expressions, we checked whether the message body contained a number of pre-set search strings and then passed the search query to our search function on the Add-in Express site. To request JSON data from an external server, you’ll need to use the makeRequest method and set its ContentType parameter to JSON. We’ve also specified that the callback method is called loadData and this method will receive the data back from the Add-in Express search service and add the items to the “links” <div> element.

Deploying Google contextual gadget

Before we can test our google gadget, we need to deploy it. First sign into your console at: https://code.google.com/googleapps/console/a/mydomain.com. Substituting the mydomain.com part with your own domain name. After you’re logged in, create a new project by clicking on the “Create project…” button. After logging in, create a new project by clicking on the 'Create project...' button.

When prompted, enter a name for your new project:

Enter a name for your new Google App project.

Next, upload the manifest file we’ve created earlier. If it is in the correct format, it should display the application name and description as illustrated below:

Upload the manifest file that will display the application name and description

With the manifest file uploaded, we’re ready to deploy the application. Do this by clicking on the “Deploy Application…” button. Deploy the newly created Google app.

A new window will open, prompting you to grant data access for the application. Click on the “Grant data access” button to proceed. A confirmation message should pop up and indicate that your application was successfully installed on your domain. Your google application was successfully installed on your domain.

Testing your Gmail contextual gadget

After you’ve deployed your application, you can log into your Gmail account and if a message contains the appropriate words, our contextual gadget will display the Add-in Express search results below the message, as illustrated in the following image:

The Add-in Express contextual gadget is installed and will display the Add-in Express search results below the message.

Thank you for reading. Until next time, keep coding!

Available downloads:

Google Gmail Contextual Gadget script

You may also be interested in:

20 Comments

  • Frederick says:

    Hi there. I tried using your manifest but ran into a problem with OAuth. It says Application Installation not allowed. OAuth1.0 version no longer available. Instead, try installing the OAuth 2.0 version. Any ideas on how to get around this?

  • Pieter van der Westhuizen says:

    Hi Frederick,

    Can you elaborate a bit more please? Where/when exactly do you get the OAuth message?

  • Lingchao says:

    Hi there,
    I have the same problem for the OAuth 1.0. I was used to be able to deploy my gadget without any problem. Recently, after I uploaded the manifest and click “Deploy application” button, I got an error which said that “The OAuth1.0 version is no longer available. Instead, try installing the OAuth2.0 version”.
    Is there anything I can do to resolve this issue?

    Thank you.

  • Andrew says:

    I’m having the same issue. When I upload the manifest and then click the ‘Deploy Application’ button, I get the message “Application installation not allowed.
    The OAuth1.0 version is no longer available. Instead, try installing the OAuth2.0 version. ”

    Any ideas?

    Thanks

  • Roberto says:

    Same issue,
    The OAuth1.0 version is no longer available. Instead, try installing the OAuth2.0 version.
    any suggestion?

    Thanks

    Roberto

  • Pieter van der Westhuizen says:

    Hi All,

    It appears Google has changed a lot with regards to contextual gadget. They’ve also implemented a new developer console.
    I’ll investigate and let you know what I come up with.

    Thank you!

  • Roberto says:

    Hi,
    I found the solution creating the project within Google APIs console and the MarketPlace SDK, no more needs to create xml files…
    Now I have a new question, using google.contentmatch.getContentMatches I can get the email body, but is there a way to get and set email labels direct from the gadget, without to call Gmail apis?

    Thanks

  • Pieter van der Westhuizen says:

    Hi Roberto,

    Thanks for letting us know!
    I haven’t been able to find a way to set email labels. It appears not to be possible, although I could be wrong :)

  • JOsh says:

    Any updates for this? This example doesn’t seem to be functional anymore.

  • Pieter van der Westhuizen says:

    Hi Josh,

    Google has changed their API and the process for creating gadgets. Unfortunately we do not have any updates for this article yet.
    However, you can read more about using the Google Marketplace SDK on https://developers.google.com/apps-marketplace/preparing

    Thanks for the comment.

  • Morten says:

    thats great that you maybe will update the article, great news! I am waiting for it.

  • rajkumar says:

    Hi Everyone,

    I am trying to create a gmail contextual gadget which allows set of users to access the gadget but I am totally confused with new Oauth2.0 . I am unable to find any Information.

    Could any one can help me In this..

    how to create a manifest file and pointing to the project gadget location

  • Pieter van der Westhuizen says:

    Hi Rajkumar,

    Unfortunately, its been a while since I worked with Gmail gadgets and things have changed somewhat.
    You can read more about using OAuth to access the Google API’s here.

    Hope this helps! Good luck!

  • vishwas says:

    Hi,
    I found the solution creating the project within Google APIs console and the MarketPlace SDK, no more needs to create xml files…
    Now I have a new question, using google.contentmatch.getContentMatches I can get the email body, but is there a way to get and set email labels direct from the gadget, without to call Gmail apis?

    Thanks

  • Pieter van der Westhuizen says:

    Hi vishwas,

    As far as I could determine, the only way to set email labels is via the api

  • Anonymous says:

    How can we get CC and BCC email ids from the Gmail contextual gadget?

    I am literally struggling with this problem.

    Any help greatly appreciated

  • rajkumar says:

    How can we get CC and BCC email ids from the Gmail contextual gadget?

    I am literally struggling with this problem.

    Any help greatly appreciated

  • Pieter van der Westhuizen says:

    Hi There,

    Have a look at this article. It show how to create an extractor. One of the extractor’s scope is emailCC. I don’t think it is possible to get the BCC field.

  • Gaurav Agrawal says:

    Hi Peiter,

    I have used this post to develop a contextual gadget before 1 year and it was useful for me that time. But now I want to develop another contextual gadget and I am not getting help to develop it. As google has deprecated the old process to develop the gadget.

    Can you please help us to develop a new contextual gadget?

  • Andrei Smolin (Add-in Express Team) says:

    Hello Guarav,

    No, we can’t. We just don’t have resources. Sorry to be of no help.

Post a comment

Have any questions? Ask us right now!