Blogger

Gadgets for Blogger

At Google, gadgets are simple HTML and JavaScript applications that can be embedded in web pages and other apps, including Blogger.

When you build a gadget for Blogger, it becomes available to millions of active bloggers. Just submit your gadget to us, and it will surface in Blogger.com where users can easily browse, configure, and add your gadget to their blog's sidebar.

So now that you know Blogger is a great distribution platform for your gadget, what are you waiting for? Get started building gadgets for Blogger now!

Get Started

Gadget Developer Guide In their simplest form, gadgets for Blogger are "Google Gadgets". If you aren't familiar with Gadgets yet, take a look at the Developer Guide to get started.
Accessing Blog Data from the Gadget Blogger's JSON APIs give gadgets access to a blog's post and comment data, letting them leverage the context of the surrounding content.
Best UI Practices for Bloger Gadgets Best practices for making your gadget look good across the large set of blog styles and layouts.
Example Gadget A simple example gadget implementing best practices.
Testing your gadget in Blogger How to test your gadget in Blogger.
Submit your gadget to Blogger Now that your gadget is bug-free and beautiful, tell the world about it!

Accessing Blog Data from the Gadget

Blogger provides read-only blog data access to gadgets. The API retrieves public post and comment data for the blog hosting the gadget. Developers can opt to retrieve the data directly in Blogger's JSON format, or retrieve the URL of the underlying Atom feed for future use.

The API is available as the google.blog feature; a gadget that depends on the data can require this feature. If you'd like your gadget to optionally access blog data but still be compliant with other Google Friend Connect containers you can make the feature optional.

Blog Posts

getPostsJson(callback)
Retrieves feed of recent posts for the current blog, returning it as JSON to the callback.

getPostsFeedUrl()
Returns the URL of the Atom feed of all posts for the current blog.

Blog Comments

getCommentsJson(callback)
Retrieves feed of recent comments (across all posts on the blog), returning it as JSON to the callback (format documented here).

getCommentsFeedUrl()
Returns the URL of the Atom feed of all recent comments.

The Current Blog Post

When a gadget is being displayed on an individual post page, these methods access the data for that post. If the gadget is not on an individual post page, these return null. You can use getCurrentCommentsFeedUrl()!=null as a test to indicate the gadget's environment.

getCurrentPostJson(callback)
Retrieves the current post as JSON, or null if there is none.

getCurrentCommentsFeedUrl()
Returns the URL of the Atom feed for recent comments on the current post, or null if there is no current post.

getCurrentCommentsJson(callback)
Returns the feed of recent comments for the current post, returning it as JSON to the callback (format documented here).

Example Snippet Accessing Blog Data

This snippet calculates the word count for the various authors on a blog based on the last few posts, using each author's OpenSocial ID as a key for ease of lookup later.


...

// Calculate wordiness of blog authors:
function onLoadFeed(data) {
  if (data.rc != 200) {
    w(["Error loading blog data"]);
    return;
  }
  var feed = data.data.feed;
  var word_counts = new Array();
  var wordiness = new Array();

  for (var i = 0; i < feed.entry.length; i++) {
    var entry = feed.entry[i];
    var word_count = entry.content.$t.split(/\s/).length;
    var osid = getOpenSocialId(entry.author[0]);
    var author = entry.author[0].name.$t;
    var authorid = getOpenSocialId(entry.author[0]);
    var key = [author,authorid];
    if (wordiness[key]==undefined)
      wordiness[key] = word_count;
    else
      wordiness[key] += word_count;
  }

  var disp = new Array();
  for (var k in wordiness) {
     disp.push(k + " : " + wordiness[k] + " words");
  }
  w(disp);
}

// Return the OpenSocial ID for an author if available
function getOpenSocialId(person) {
  var extendedProperty = person.gd$extendedProperty;

  if (extendedProperty && extendedProperty.name == "OpenSocialUserId") {
    return extendedProperty.value;
  } else {
    return null;
  }
}

// Write output to a display element on the gadget
function w(arr) {
  var str = "<ul>";
  for (var e in arr) {
    str += "<li>"+arr[e]+"</li>";
  }
  str += "</ul>";
  document.getElementById('display').innerHTML = str;
}

Best UI Practices for Blogger Gadgets

Bloggers want to look good on the web. Follow these best practices so your gadget blends seamlessly with the many themes bloggers use.

Support A Range of Widths

In Blogger, the available width for your gadget depends both on the blog's template, and on the location where the gadget is inserted in the blog. The sidebars in Blogger.com templates range from 150px - 360px wide, though some templates have sidebars that resize to be wider when the browser window is stretched. In addition blog administrators can overwrite the default sidebar width.

In addition, gadgets can be added to the blog's side bar, header, or footer regions as shown by the orange rectangle in the images below.

             

This means your gadget should be flexible to work well at almost any width. Be sure to test your gadget in a variety of sizes in the blog before submitting your gadget.

Managing Gadget Height

By default, gadgets are 200 pixels high. You can use the <ModulePrefs> attribute height="nn" to specify a static height that is bigger or smaller than the default. However most gadgets will need to dynamically change their height. Follow these guidelines to dynamically resize the height of your gadget.

Inherit the Blog's Style

The skins feature provides access to key Blogger theme parameters. This feature is shared between Blogger and Google Friend Connect and the same skin parameters are used in both. In Blogger, the parameters are automatically inherited from the blog's template, so gadgets can easily blend in with the look and feel of the containing page. Blog owners can also override skin values if they wish to do so.

To access the parameters, a gadget asks for the skins feature:

<Optional feature="skins" />

It can then access parameters via the API, setting styles of elements via DOM manipulation:

<$("someElement").style.borderColor = gadgets.skins.getProperty('BORDER_COLOR');

Core Skin Parameters

These parameters are the most critical to use, and are always provided by the container. Each of these maps to an equivalent CSS style and can be added to HTML elements.

BORDER_COLOR
Color of border of gadget, or 'transparent' if no border desired. Use this for the style of any border around the entire gadget; do not assume that the border is always visible (many blogs do not frame gadgets with borders).

CONTENT_BG_COLOR
Background color to use for main portion of gadget. This usually matches the background color of the blog's sidebar, but in any case is chosen by the container to make gadgets look good.

CONTENT_LINK_COLOR
Color of links in the main portion of gadget; chosen by the container to be readable against CONTENT_BG_COLOR, work well with CONTENT_TEXT_COLOR, and be consistent with links elsewhere on the page.

CONTENT_TEXT_COLOR : Color of primary or most-displayed text in main portion of gadget; chosen by the container to be readable against CONTENT_BG_COLOR and consistent with text on the rest of the page.

FONT_FACE
Font face to use by default; chosen to be consistent with the rest of the content.

Extended Skin Variables

These may be used by a page owner to further tweak appearance on a per-gadget basis. They are not needed for all gadgets, but if your gadget uses these concepts, it should allow these variable to control their style.

CONTENT_HEADLINE_COLOR
Text color for titles or headlines as opposed to body text. Defaults to CONTENT_TEXT_COLOR.

CONTENT_SECONDARY_TEXT_COLOR
An alternative color for secondary text that complements CONTENT_TEXT_COLOR. Defaults to CONTENT_TEXT_COLOR.

CONTENT_SECONDARY_LINK_COLOR
Color for links in secondary text. Defaults to CONTENT_LINK_COLOR.

ENDCAP_BG_COLOR
Color for top and bottom cap sections for the gadget; defaults to CONTENT_BG_COLOR.

ENDCAP_LINK_COLOR
Color for links within top / bottom cap sections; defaults to CONTENT_LINK_COLOR.

ENDCAP_TEXT_COLOR
Color for text within top / bottom cap sections; defaults to CONTENT_TEXT_COLOR.

ALTERNATE_BG_COLOR
Used for alternating rows in large list; defaults to CONTENT_BG_COLOR

CONTENT_VISITED_LINK_COLOR
Visited link color; defaults to CONTENT_LINK_COLOR.

Using Canvas Mode

To create a canvas("big mode") view of your gadget, where the gadget expands horizontally to span the entire gadget area, you must define a section for the "canvas" view type, as follows:

<Content type="html" view="canvas" />

Keep it simple

Each element, style, or graphic you add to your gadget, is something else that might clash with the containing blog's style. You want your gadget to blend seamlessly into as many blogs as possible. Avoid adding elements that cannot be skinned using the above defined skin parameters.

Do not add a title into your gadget's UI. Blogger will add the title automatically outside of the gadget in the same style as other gadget titles on the blog.

Most importantly, test your gadget on a number of different blogs. Modify the blog's background color, text color, and font face to ensure your gadget blends with a wide range of templates.

Example Gadget

Here is a very simple Friend Connect powered gadget that takes advantage Blogger's JSON API. The gadget displays the current post's comments and highlights the comment if it was made by the viewer's friend. When the gadget is embedded in a blog, it will match the blog's style because it inherits several skin parameters.

The example gadget is also hosted here: example gadget.

<?xml version="1.0" encoding="UTF-8"?>
<Module>
<ModulePrefs height="300" title="BlogSocial">
  <Require feature="opensocial-0.7"/>
  <Require feature="google.blog"/>
  <Require feature="skins"/>
  <Require feature="views"/>
 </ModulePrefs>
 <Content type="html">
   <![CDATA[
   <script type="text/javascript">
     var friendProfiles = {};
     var blog;

     function goToCanvas() {
       var view = gadgets.views.getSupportedViews()['canvas'];
       gadgets.views.requestNavigateTo(view);
     }

     /**
      * This method is called after your friend data is loaded. It parses the friend data and
      * saves the profile ids of your friends, then fetches the blog data.
      */
     function onLoadFriends(data) {
       if (data.responseItems_.viewerFriends.data_ == null) {
         document.getElementById("output").style.textAlign = "center";
         if (gadgets.views.getCurrentView().getName() == "canvas") {
           document.getElementById("output").innerHTML = 'Sign in using the link above';
         } else {
           document.getElementById("output").innerHTML = 
	     '<a style="color:' + linkColor + '" href="javascript:void(0);" 
	     onclick="goToCanvas();">Sign in to Friend Connect!</a>';
         }
         return;
       }

       var friends = data.responseItems_.viewerFriends.data_.array_;
       for (var i = 0; i < friends.length; i++) {
         var id = friends[i].fields_.id;
         friendProfiles[id] = "true";
       }

       // Get the feed data
       blog = new google.Blog(function() {
         // This callback is run as part of the constructor of google.Blog to signify
         // that everything was initialized. Once the constructor has
         // completed and then call getCommentsJson
         blog.getCommentsJson(onLoadFeed);
       }, window.name);
     }

     /**
      * This method parses the feed data that was returned by the call to fetch the blog data.
      */
     function onLoadFeed(data) {
       var list = document.getElementById("output");

       if (!data.data) {
         list.innerHTML = "An error occured fetching the feed data";
       }

       data = data.data;

       if (!data.feed.entry || data.feed.entry.length == 0) {
         list.innerHTML = "No comments on this blog!";
       }

       for (var i = 0; i < data.feed.entry.length; i++) {
         var entry = data.feed.entry[i];
         var dt = document.createElement("DT");
         dt.style.paddingTop = "10px";
         var dd = document.createElement("div");
         var href;
         for (var j = 0; j < entry.link.length; ++j) {
           if (entry.link[j].rel == "alternate") {
             href = entry.link[j].href.replace(/#/, "#comment-");
           }
         }

         var a = document.createElement("A");
         a.style.color = linkColor;
         a.setAttribute("href", href);
         a.appendChild(document.createTextNode(entry.author[0].name.$t + " wrote..."));
         dt.appendChild(a);
         dd.appendChild(document.createTextNode(entry.content.$t));
         list.appendChild(dt);
         list.appendChild(dd);

         // extendedProperty is Blogger's extension to ATOM 1.0 that contains the
         // OpenSocial user id of the author if the author is a public follower
         // of the blog. This field will not be present if the author is not a
         // public follower of the blog.
         var extendedProperty = entry.author[0].gd$extendedProperty;

         if (extendedProperty && extendedProperty.name == "OpenSocialUserId") {
           if (friendProfiles[extendedProperty.value]) {
               dt.style.backgroundColor = "yellow";
               dd.style.backgroundColor = "yellow";
           }
         }
       }
     }

     var linkColor;
     var textColor;
     var backgroundColor;
     function initData() {
       textColor = gadgets.skins.getProperty('CONTENT_TEXT_COLOR');
       document.getElementById("output").style.color = textColor;

       linkColor = gadgets.skins.getProperty('CONTENT_LINK_COLOR');
       document.getElementById("canvas-link").style.color = linkColor;

       backgroundColor = gadgets.skins.getProperty('CONTENT_BG_COLOR');
       document.body.style.backgroundColor = backgroundColor;

       // Show canvas mode link if appropriate
       if (gadgets.views.getCurrentView().getName() != "canvas") {
         document.getElementById("canvas-link-container").style.display = "block";
       }

       var req = opensocial.newDataRequest();
       req.add(req.newFetchPersonRequest('VIEWER'), 'viewer');
       req.add(req.newFetchPeopleRequest('VIEWER_FRIENDS', {}), 'viewerFriends');
       req.send(onLoadFriends);
     }
     gadgets.util.registerOnLoadHandler(initData);

   </script>
   <div style="display:none;float:right;font-size:80%" id="canvas-link-container">
     <a id="canvas-link" href="javascript:void(0);" onclick="goToCanvas();">Canvas mode</a>
   </div>
   <div style="clear:both"></div>
   <div id="output" style="overflow:auto; height:270px;font-size:90%"></div>
  ]]>

  </Content>
</Module>

Testing your Gadget in Blogger

Since a gadget for Blogger is a Google Gadget, follow this guide for testing and preparing your Google Gadget for publication. One complete, read and follow the sections below describing how to test your gadget in Blogger.

Setting up a Test Blog

Create a test blog with some post and comment data to use during testing:

  1. Download test_blog_data.xml.zip; uncompress the file and save test_blog_data.xml to your computer.
  2. Go to the Import Blog Page
  3. Upload test_blog_data.xml and follow the instructions to import the blog content and publish it.

Now you're ready to start testing.

Debugging your gadget in Blogger

The functionality and appearance of your gadget depends on the blog that contains it. Therefore, the best way to debug your gadget is to test it in the context of an actual blog on Blogger.com. Above we described how to create a test blog, below we discuss how to add your gadget to your test blog and debug it on the blog.

First, make sure that your gadget XML file is hosted on a public web server, and that you have a test blog set up. From Blogger.com, go to Layout -> Add a Gadget ->Add your Own, enter your gadget's URL, and then save. The gadget will be added to your blog; click View Blog to view and test your gadget in the blog.

Testing Gadget Configuration in Blogger

Blogger provides a standard UI for adding and configuring gadgets. You should test that any UserPrefs you've defined can correctly be configured by the blog administrator in Blogger.com.

From Blogger.com, click the Layout tab, then click Add a Gadget. From the Gadget Diretory, choose Add your own. This allows you to add your gadget by its URL (note: the gadget must be hosted on a public web server).

When you add a gadget, it will display a preview and show any UserPref parameters that can be configured. Test updating various configuration values and adding your gadget to your test blog. Confirm your gadget works as expected on the blog itself.

Testing Width and Height

In Blogger, the available width for your gadget depends on the location it is inserted. Gadgets can be added to the blog's side bar, header, or footer regions as shown by the orange rectangle in the images below.

             

From Blogger.com, click the Layouts tab for your test blog. Drag your test gadget into the following regions, and click Save to view and test your gadget in those locations.

  • side bar
  • header area
  • footer area

Also test the gadget in the sidebar of several different templates, since sidebar widths vary from template to template. From Blogger.com, click the Layout tab for your blog. Then click Pick a new Template. From the Template Picker, test that your gadget works well in the side bar of these templates:

  • Scribe (150px sidebar)
  • Rounders (215px sidebar)
  • Tekka (360px sidebar)
  • Denim Stretch (variable widgth sidebar)

Testing Style, Fonts and Colors

As described above, your gadget should use skinning parameters to inherit the blog's style including text colors, background colors, and font face. Test that your gadget correctly inherits the blog's style by testing it on a variety of different blog templates.

From Blogger.com, click the Layout tab. Then click Pick a new Template. From the Template Picker, confirm your gadget correctly inherits styles from the following templates:

  • Minima Dark
  • Denim
  • No. 897
  • Rounders
  • The more the better!

You may want to also edit the blog's Fonts and Colors directly. From the Layouts tab, click Fonts and Colors to control specific font and color choices for the blog and verify they are correctly inherited by your gadget.

Submit your gadget

Once you've throughougly tested your gadget, and followed Blogger's Best UI Practices, you're ready to submit your gadget.

Submit your gadget to Blogger now!

Back to top

Authentication required

You need to be signed in with Google+ to do that.

Signing you in...

Google Developers needs your permission to do that.