In the introduction you used the API Explorer to fetch your public profile. If the REST API is the core of the platform, the plugins are portals into Google+ from your web presence. This chapter explores these social plugins.
Social plugins are snippets of JavaScript code and HTML markup. They can be easily added to existing web pages and applications with only a few lines of code. They are also highly configurable.
A great way to learn the social plugins is to use them. You will add them to a blog called Baking Disasters. Baking Disasters consists of a static HTML index page and two entry pages that describe a couple of particularly disastrous baking attempts. You can see the initial version of the blog here: http://bakingdisasters.com/social-blog/initial/. The entry pages are a great place to experiment with the +1 button, and the index is an ideal candidate for the Google+ badge.
Before there was Google+ there was the +1 button. Announced at Google I/O in 2011, this feature predates every other component of the Google+ platform. It provides a one-click interface for your users to publicly identify their favorite content. Once users have +1’d a page, they have the option to share it on Google+.
From your user’s perspective the +1 button is quite simple. They see your page, and since your content makes their eyes light up in excitement, they click the +1 button.
Figure 2-1 shows what happens next. The button turns red and their icon is added to the inline annotation. After this, the page is listed in the +1’s tab on their Google+ profile, and their endorsement appears in annotations for this page. These annotations appear on your page as well in Google search result listings. Annotations are customized to the viewing user using their circles on Google+.
After your user has +1’d your webpage, they will see the share dialog. It allows them to share your content on Google+. You can use structured markup to specify the title, description, and thumbnail image that are used.
Finally, the +1 triggers a custom JavaScript callback. This allows you to leverage their interest in creative and interesting ways.
Behind the scenes, a bit more happens. Many systems organize to provide this functionality. When the +1 button renders, information is loaded to provide your user a personalized annotation. When they click, a page fetcher visits your site in real time to extract your page’s snippet: a short summary of your page. This summary is sent back to the +1 button, allowing the user to preview what they are about to share on Google+. Finally, when they share, an activity is posted to their stream.
Figure 2-2 illustrates this in detail.
The web page sources plusone.js
from Google.
The web page renders the +1 button.
The +1 button fetches current +1 count.
Your user clicks the +1 button.
The +1 button communicates the click to Google.
Google fetches the target page.
Google generates a snippet for the target page.
The snippet is provided in the response to the +1 button click to preview the content that can be shared.
Your user shares the snippet for the target page on Google+.
Now that you understand how the +1 button works, it is time to use it.
The +1 button is very easy to add to a web page. In its most basic form it requires only two lines of code. From this starting point you can further configure the button to match your needs.
The Google+ platform social plugins feature configuration tools. This is the best place to start. The +1 button configuration tool can be found at https://developers.google.com/+/plugins/+1button/. The configuration tool, pictured in Figure 2-3, consists of a form, a preview, and a text area containing code. Play with the form. Notice that the +1 button and code automatically update.
Add the default +1 button to one of the entries on Baking
Disasters. Copy the +1 button element into the place that you would like
it to render. Based on the layout of the entry, a spot to the right of
the header will work perfectly. Wrap the button in a div
to float it right, as shown in Example 2-1.
Example 2-1. The +1 button markup
<header>
<div
style=
"float: right;"
>
<div
class=
"g-plusone"
data-annotation=
"inline"
></div>
</div>
<h2>
Doom Bread</h2>
</header>
The +1 button markup is only half of the story, though. Paste the
JavaScript into the page too. It can be placed anywhere on the page,
including just before the </body>
tag, as shown
in Example 2-2. When it loads, it transforms all elements
with class="g-plusone"
into a +1
button.
Example 2-2. The asynchronous version of the +1 button JavaScript
</footer>
<script
type=
"text/javascript"
>
(
function
()
{
var
po
=
document
.
createElement
(
'script'
);
po
.
type
=
'text/javascript'
;
po
.
async
=
true
;
po
.
src
=
'https://apis.google.com/js/plusone.js'
;
var
s
=
document
.
getElementsByTagName
(
'script'
)[
0
];
s
.
parentNode
.
insertBefore
(
po
,
s
);
})();
</script>
</body>
</html>
Reload the page to see the +1 button, as shown in Figure 2-4.
The default width of 450 pixels has mangled the entry title. Sensible defaults are not always perfect for every layout. Return to the configuration tool and specify a width. Change the width to 250 pixels to leave room for longer titles, as shown in Example 2-3 and pictured in Figure 2-5.
Copy the updated code, and paste it into the entry.
Example 2-3. +1 button markup configured to 250 pixels wide
<header>
<div
style=
"float: right;"
>
<div
class=
"g-plusone"
data-annotation=
"inline"
data-width=
"250"
></div>
</div>
<h2>
Doom Bread</h2>
</header>
Reload the page to observe the change. It should look like Figure 2-6.
You can return to the configuration tool to explore the other options that it provides.
The configuration tool provides a quick way to grab some code and run with the +1 button, but digging deeper unlocks more options.
The rest of the +1 button documentation can be found below the configuration tool. It documents all of the configuration options for the +1 button, including many that are not covered by the configuration tool.
For example, the documentation describes all of the tag attributes
in detail. The annotation is pretty cool, but sometimes there isn’t
enough space. Scanning the documentation it appears that the annotation
is configurable. The options include inline
, the default, a smaller bubble
, and none
. Changing the annotation to none
, as shown in Example 2-4,
the +1 button shrinks to a much smaller footprint.
Example 2-4. +1 button markup with no annotation
<header>
<div
style=
"float: right;"
>
<div
class=
"g-plusone"
data-annotation=
"none"
></div>
</div>
<h2>
Macaron</h2>
</header>
The floating div
layout slides
the smaller +1 button to the right as pictured in Figure 2-7.
There are many more parameters that you may find useful. Explore the documentation to learn about them.
+1’ing a page creates content on Google+. It inserts a brief summary on the +1’s tab of the user’s profile, and an activity in their stream, if they share. The title, description and thumbnail image make up the snippet. You can customize your snippet to ensure that all of your pages look great on Google+.
By default the +1 button creates a best guess snippet. This is usually pretty good, but you know your content best. You can specify a much better snippet. The snippet can be specified using either schema.org markup or Open Graph tags.
Google recommends that you use schema.org markup to specify your snippet. Adding schema.org markup involves adding attributes to your existing content, so you do not need to add any new tags. It also allows top search engines, like Google and Bing, to parse your pages more easily.
Now that you understand why schema.org markup is a great solution, add it to a page. The first step is to select the correct schema. There’s a handy list published at http://schema.org/docs/full.html. It includes all of the schemas in one long page. In general, use the most specific schema that is appropriate to your content. It allows you to describe your content as richly as possible.
Scanning the list, it appears that there’s a recipe schema: http://schema.org/Recipe. This is perfect for Baking Disasters. Add it to the macaron entry.
The recipe does not have content to match every single field in the schema, but it’s wise to match as many as you can. The social plugins only understand the fields that are inherited from the thing schema, but complete markup provides the greatest benefits from search engines and future features of the Google+ platform. For example, the history API, which is currently in developer preview, makes use of many other schemas.
Add the itemscope
and itemtype
attributes to the parent element of
the recipe, as shown in Example 2-5. On the macaron entry,
the section element with class content
is appropriate.
Example 2-5. Schema.org itemscope and itemtype
.Schema.org itemscope and itemtype<p>
Because sometimes molecular gastronomy explodes.</p>
</header>
<section
class=
"content"
itemscope
itemtype=
"http://schema.org/Recipe"
>
<section
class=
"post-body"
>
<header>
Next, mark individual elements by adding itemprop
attributes. Start with the properties
inherited from the thing schema—description
, image
, name
, and url
—and follow by marking up the recipe
specific fields such as ingredients
and recipeInstructions
. The resulting
code is shown in Example 2-6.
Example 2-6. Schema.org recipe markup on the macaron page
<header>
<div
style=
"float: right;"
><div
class=
"g-plusone"
data-annotation=
"none"
></div></div>
<h2
itemprop=
"name"
>
Macaron</h2>
</header>
<img
class=
"baking-photo"
src=
"images/macaron.png"
itemprop=
"image"
>
<p
itemprop=
"description"
>
Few baked goods are as prone to explosions as the delicious and delicate French macaron. There's something about a hard outer shell attempting to hold back the pressure of expanding almond-flour-goo that's reminiscent of a poorly designed steam locomotive.</p>
<h3>
The Recipe</h3>
<ul>
<li
itemprop=
"ingredients"
>
1 cup powdered sugar</li>
<li
itemprop=
"ingredients"
>
1/4 cup baker's superfine sugar</li>
<li
itemprop=
"ingredients"
>
3/4 cup almond flour</li>
<li
itemprop=
"ingredients"
>
3 egg whites</li>
</ul>
<ol
itemprop=
"recipeInstructions"
>
<li>
Mix powdered sugar and almond flour</li>
Reload and +1 the page. Something slightly different happens: rather than using a best guess snippet, the +1 button reads the schema.org markup. See the improvement in Figure 2-8.
Schema.org markup is the preferred option for specifying your
snippet, but other options are available. When schema.org markup is not
present, the +1 button looks for Open Graph markup. Open Graph markup
consists of meta
elements within your
HTML head. These meta elements specify details about your page. Using
Open Graph may make more sense if you already have social sharing
buttons from other services on your site that use Open Graph.
Open Graph is less expressive, but it is also simpler. Add
elements to the HTML header of the doom bread page: meta
tags with property og:title
, og:image
and og:description
, as shown in Example 2-7.
Example 2-7. Open Graph markup on doom bread
<!DOCTYPE html>
<html>
<head>
<title>
Baking Disasters</title>
<link
rel=
"stylesheet"
href=
"style.css"
/>
<link
rel=
"shortcut icon"
href=
"images/logo_favicon.png"
/>
<link
rel=
"canonical"
href=
"http://bakingdisasters.com/blog/doom-bread.html"
/>
<meta
property=
"og:title"
content=
"Doom Bread on Baking Disasters"
/>
<meta
property=
"og:image"
content=
"http://bakingdisasters.com/blog/images/doom-bread.png"
/>
<meta
property=
"og:description"
content=
"Is it a bread or is it a roll? Within this layery monstrosity is the
essence of fatty deliciousness."
/>
</head>
<body>
As you can see, both of these methods provide a way to specify your snippet. Which method is best depends on the implementation details of your application.
You have learned a lot about the what the +1 button can do, but you haven’t written very much code yet. This is about to change. The callback is a software hook provided by the +1 button.
The callback allows you to trigger your own JavaScript code when the +1 button is clicked. It can call any function in the global namespace. Just supply it as a parameter to the +1 button, as shown in Example 2-8.
Example 2-8. A simple callback and +1 button markup configured to call it
<script>
function
onPlusone
(){
alert
(
"Hello, world!"
);
}
</script>
<div
class=
"g-plusone"
data-callback=
"onPlusone"
></div>
This unlocks a lot of potential. When a user clicks the +1 button they have just indicated their interest in your content. This is a great opportunity to engage them further.
On Baking Disasters you can leverage the callback to recommend other content that the user might enjoy. When a user +1’s the page you can reveal this recommendation. The recipe page seems like a great place to perform this integration.
On a more complex site the task of determining recommended would likely involve an AJAX call, but Baking Disasters is simple. It hosts only two recipes. The only option is to recommend the other recipe when the user clicks on the +1 button.
Include the recommendation in the page and hide it with CSS. When the callback executes, inspect the button state and reveal or hide the recommendation appropriately, as shown in Example 2-9.
Example 2-9. A JavaScript callback that reveals content when your user +1’s your page
function
onPlusone
(
jsonParam
)
{
var
recommendedContent
=
document
.
getElementById
(
"recommended-content"
);
if
(
jsonParam
.
state
==
"on"
)
{
recommendedContent
.
className
=
"active"
;
}
else
{
recommendedContent
.
className
=
""
;
}
}
When the +1 button is toggled on, the recommendation is revealed. When the button is toggled off, it is hidden as pictured in Figure 2-9.
Figure 2-9. Clicking on the +1 button triggers the callback and reveals the recommendation in the bottom screen shot.
The main callback is the best place to add interesting
functionality, but there are a couple other callbacks. These callbacks,
onstartinteraction
and onendinteraction
, trigger when a user begins
and ends their interaction. They are very useful if you have a Flash
advertisement or video that appears on top of your +1 button bubble. You
can use them to hide the flash content while the user interacts with the
+1 button and reveal it again when their interaction ends.
The callback is where developing with the +1 button really comes to life. This is your opportunity to integrate the +1 button into your core features and connect with your most active users. Be creative and have fun.
AJAX applications throw a bit of a wrench into the system
described above. In general AJAX applications track state using hash
fragments. Hash fragments are the part of the URL after the # symbol.
For example, a user may enter an AJAX application at http://example.com/
and navigate to a view of
their profile at http://example.com/!profile/123
. During this
navigation the domain name and path do not change. To clients that do
not execute JavaScript, like web crawlers and the +1 button’s snippet
fetcher, these URLs appear the same even though they contain very
different content for the user.
Luckily, this problem has already been solved. Several years ago Google published a technique to make AJAX applications crawlable. It is described here: https://developers.google.com/webmasters/ajax-crawling/docs/getting-started. Because the +1 button fetcher is similar to web search crawlers, you can leverage this existing solution.
When you specify the target page for your +1 button, target a URL
that specifies the state in a GET parameter instead of a hash fragment.
For example, when you render a +1 button on http://example.com/#!profile/123
specify the
URL target to be http://example.com/?_escaped_fragment_=profile/123
.
Your web server, of course, must be able to understand the GET parameter
and respond with the correct HTML.
There are many ways to implement this functionality on your web server. One approach is be to replicate all client side JavaScript behavior server side. In doing so, the crawlable version of every URL will always render the exact same HTML as if it were navigated to via AJAX. This solution will provide the best user experience.
If replicating this functionality server-side is prohibitively
expensive, you may want to consider HTML snapshots. Create HTML
snapshots by using headless browser programs, like those used for
testing web applications, to regularly generate crawlable versions of
your pages. When a client requests the _escaped_fragment_
version of a page, your web
server would then respond with the snapshot version. This technique is
described in more detail on the
previously linked guide
to making crawlable AJAX applications.
Sometimes things don’t work as expected. Sometimes the +1 turns pink and shows an exclamation point, as shown in Figure 2-10. This icon does not help very much on its own, but just behind the covers there are more details. Modern web browsers provide powerful JavaScript debugging tools such as Firebug for Mozilla Firefox and the Chrome developer tools.
If you see a pink +1 button, open up Chrome’s developer tools and switch to the network panel. Inspect the request for rpc as shown in Figure 2-11. This is the back-end API request made by the +1 button. You should see more details in the response body.
You may see “Backend Error” in the response. This means that the Google servers, which generate the snippet, were unable to reach or parse your page. Since the error message does not contain details, this can be a challenging issue to troubleshoot. Here’s a checklist of common causes.
Reachable webpage: Is your web
page reachable from the Internet? If you’re developing on http://localhost
, or within a corporate
intranet, the snippet fetcher cannot reach your page. Be sure to publish
it somewhere that Google can access it.
Page response time: Since the snippet is generated in real time, your web server must be reasonably responsive. If page loads take more than a few seconds, you may encounter issues.
User agent filtering: The user agent of the snippet page fetcher is not part of the documented API. Do not filter, redirect or block traffic based on user agent.
Valid snippet markup: Paste the URL for your webpage into the Webmaster Central Rich Snippet Testing Tool found at http://www.google.com/webmasters/tools/richsnippets. This will fetch your page and validate your rich snippet markup.
Valid HTML: Does your website use valid HTML markup? Check it with a tool such as W3C’s validation service: http://validator.w3.org. A few warnings and errors are probably fine, but the more errors your page contains, the more challenging it is to parse.
If you’ve gone through this checklist and you’re still seeing an error when +1’ing your webpage, you can always reach out to the Google+ team for help. Flip ahead to the last chapter of this book to learn more about support. Do not forget to link to a place where the issue is happening.
The Google+ badge makes it easy for you to advertise your presence on Google+ to visitors of your website. The badge comes in two flavors: one for user profiles and another for pages. Both of these badges link to you on Google+ and provide a way for visitors to add you to their circles from the badge itself, as pictured in Figure 2-12. The version of the badge for pages also includes a +1 button, consolidates the count of +1’s from your Google+ page and homepage, and opens the door for Direct Connect.
Direct Connect allows visitors to navigate to your Google+ page directly from Google Web Search. Searches for the title of your page prefixed with a plus sign, such as +android for Android, will automatically forward to your page instead of listing search results. Additionally, since the leading plus sign demonstrates interest on the part of your visitor, they are automatically prompted to add your page to one of their circles, as pictured in Figure 2-13.
Baking Disasters is not a person, so you must use the badge for Google+ pages. Baking Disasters already has a Google+ page, shown in Figure 2-14, that you can use for the badge. If you don’t have a page already, you can create one now. Follow the step-by-step tutorial to create one here: https://plus.google.com/pages/create.
Now that you have both pieces, a homepage and a Google+ page, you can set up the badge. Just like the +1 button, the badge provides a configuration tool that is accessible at https://developers.google.com/+/plugins/badge/ and shown in Figure 2-15. Several more advanced configuration options are documented below. Use the configuration tool to add a page badge to the index page.
Unlike the +1 button, the badge needs to know the page or profile that it links to. The configuration tool has a drop-down that lists your Google+ profile and the pages you manage.
Alternatively, if you are creating a badge for a page that you do not manage, or for a profile that is not yours, use the other option to specify the badge target by copying and pasting the URL as shown in Figure 2-16 and Figure 2-17.
Just like the +1 button configuration tool, the badge configuration tool automatically produces a preview and source code. The default badge is a bit large for Baking Disasters, but with a few clicks you can make it smaller. A small badge with a width of 170 pixels should fit nicely into the header. This configuration is shown in Figure 2-18.
The code for the badge has a two parts: JavaScript and HTML markup. The JavaScript portion probably looks familiar; it’s the exact same code that renders the +1 button. You only need to include it once, so if you have any other Google+ plugin already on your page, you can ignore it. Next, the HTML markup must be placed where you would like the badge to render.
Here’s the updated index page with the badge source in Example 2-10 and a screenshot of the rendered badge in Figure 2-19.
Example 2-10. The Baking Disasters blog index page: now with a Google+ badge in the header
<header
class=
"blog-header"
>
<div
class=
"header-badge"
>
<div
class=
"g-plus"
data-width=
"171"
data-href=
"//plus.google.com/116852994107721644038?rel=publisher"
></div>
</div>
<a
href=
"index.html"
>
<img
id=
"blog-logo"
src=
"images/logo.png"
/></a>
<h1>
Baking Disasters</h1>
<p>
Because sometimes molecular gastronomy explodes.</p>
</header>
...<!-- Asynchronously load the +1 button JavaScript -->
<script
type=
"text/javascript"
>
(
function
()
{
var
po
=
document
.
createElement
(
'script'
);
po
.
type
=
'text/javascript'
;
po
.
async
=
true
;
po
.
src
=
'https://apis.google.com/js/plusone.js'
;
var
s
=
document
.
getElementsByTagName
(
'script'
)[
0
];
s
.
parentNode
.
insertBefore
(
po
,
s
);
})();
</script>
</body>
</html>
With the badge installed, visitors can now discover Baking Disasters on Google+ and add its Google+ page to one of their circles.
Social plugins add a lot of value, but this value comes at a small cost. They load and execute JavaScript code. This additional code can slow down page loads and reduce the quality of your user’s experience. Luckily, there is a bag of tricks to pull from to mitigate this. These tricks work for any social plugin.
You may already be using asynchronous loading. The configuration tools supply you with asynchronous code by default. Asynchronous loading delays the rendering of all plugins until later in the page load, which makes pages feel more responsive.
If you are using this JavaScript to load your plugins, as shown in Example 2-11:
Example 2-11. Synchronous +1 button JavaScript code
<script
src=
"https://apis.google.com/js/plusone.js"
></script>
change it to this code, as shown in Example 2-12:
Example 2-12. Asynchronous +1 button JavaScript code
<script>
(
function
()
{
var
po
=
document
.
createElement
(
'script'
);
po
.
type
=
'text/javascript'
;
po
.
async
=
true
;
po
.
src
=
'https://apis.google.com/js/plusone.js'
;
var
s
=
document
.
getElementsByTagName
(
'script'
)[
0
];
s
.
parentNode
.
insertBefore
(
po
,
s
);
})();
</script>
To take this philosophy one step further, you can even delay the
execution of the asynchronous loader until after most of your page has
been downloaded and parsed. Move the asynchronous JavaScript to the
bottom of your page just before the closing </body>
tag.
By default the social plugins search the entire page for
placeholder elements, such as <g:plusone>
, <g:plus>
and <div class="g-plus"></div>
, and
replace them with the plugins. If your page is very large, this may be
inefficient.
You can reduce the size of this search with explicit rendering. When you source the JavaScript use a special piece of JSON to prevent the initial page scan. The responsibility of rendering now falls on you, but along with this responsibility comes the power to specify exactly where to render the plugins. Code illustrating both the special JSON and the explicit rendering is shown in Example 2-13.
Example 2-13. Explicit +1 button rendering
<!DOCTYPE html>
<html>
<head>
<title>
Baking Disasters</title>
<link
rel=
"stylesheet"
href=
"style.css"
/>
<script
type=
"text/javascript"
src=
"https://apis.google.com/js/plusone.js"
>
{
parsetags
:
'explicit'
}
</script>
</head>
<body>
...<section
class=
"content"
>
<section
class=
"post-summary"
id=
"macaron"
>
<div
class=
"g-plusone"
data-href=
"http://bakingdisasters.com/social-blog/final/macaron.html"
>
</div>
<header><h2>
Macaron</h2></header>
...</footer>
<script
type=
"text/javascript"
>
gapi
.
plusone
.
go
(
"macaron"
);
gapi
.
plusone
.
go
(
"doom-bread"
);
</script>
</body>
</html>
Using your own code to render the
plugin has one caveat. You must load the plusone
.js
file
synchronously.
If you have an extremely large number of social plugins on one page, you may want to delay their rendering until the user interacts with elements near the plugin.
Specify a placeholder image for the social plugin and add a
mouseover
event handler to content
that the user is likely to mouse over, before they can reach the social
plugin. To keep this from being too jarring, use an image of the
rendered plugin as a placeholder. Example 2-14 shows this
trick being used on the Baking Disasters index page.
Example 2-14. Delayed +1 button rendering
<script> function renderPlusone(placeholderId, targetUrl, origin) { origin.onmouseover = null; gapi.plusone.render(placeholderId, {"annotation":"none", "href":targetUrl});} </script> <section class="content"> <section class="post-summary" id="macaron"
onmouseover="renderPlusone('plusone-macaron', 'http://bakingdisasters.com/blog/macaron.html', this)"> <div id="plusone-macaron"
style="width:38px;height:24px;display:inline-block; background-image:url(images/plusone_button_placeholder.png);"> </div> <header><h2>Macaron</h2></header> <p>Few baked goods are as prone to explosions as the delicious and delicate
When visitors reach the page they will see the placeholder image of the +1 button until they mouse over the recipe summary.
Can you see a difference between the left and right versions in Figure 2-20? If the answer is no, you’re doing it correctly. The left browser window contains the placeholder while the one on the right contains the rendered button.
Use this technique only where necessary. Any image placeholder you use must be kept up to date as the plugins change. Also, no matter how perfect the placeholder image is, it will not be able to display annotations or existing +1 button state. If they have already +1’d your page, they will not be able to see it until they trigger the plugin to render.
There are always enhancements to the existing plugins and entirely new features being explored by the Google+ team. Before launching new features to everyone, they’re tested with a preview group. If you’d like to stay on the bleeding edge you can join this preview group to gain early access to new features.
To join the platform preview group complete the form at http://www.google.com/+/learnmore/platform-preview with an email address for a Google+ profile. When new features enter publisher preview you will be notified via email at that address. You will only see publisher preview features while you’re logged in to this account.
Platform preview is a great opportunity to experiment with features before full release. You can configure the new features, such as new display options, so only you can see them. Once the features enter graduate to full release they will automatically appear to all visitors.