Blog from October, 2015

On this page

Our guest blog post today is by Michael Kuhl, Sr. Manager of IT Operations at HomeAway

In this post, Michael generously provides a detailed look into HomeAway's impressive Bob Swift Atlassian Add-ons Customer Success Story, which was recently selected as a finalist for Atlassian's "ShipItLive" contest at the 2015 Atlassian Summit in San Francisco.

If you have not yet done so, you'll want to watch the video for this HomeAway Customer Success story here. It's definitely a must see!

Summary (TL;DR)

HomeAway launched a global wallboard network (120 boards and counting) that delivers hyper-local, user-generated content using Confluence and several Bob Swift Atlassian Add-ons.

About HomeAway

HomeAway operates the world’s largest online marketplace of vacation rentals with over a million houses, condos, and even castles in 190 countries that whole families and groups of friends can enjoy a whole vacation together.  With a team of about 1,900 employees spread across 20 offices in 12 countries, it’s critical that the team be able to collaborate and communicate effectively as we work to deliver great experiences for our travelers and for our vacation rental owners and managers.

The Problem

Each office has a number of wallboards situated within its work areas and common areas.  Wallboards can be a great way for teams to collaborate around actionable information pertinent to their work and a great medium for broader communication across the organization.  Unfortunately, most of those wallboards were being underutilized.

The wallboards were running a quickly put-together in-house app that had limited location-targeting ability, rudimentary real-time notifications, and required a service desk ticket to update.  Creating content required having your own web server (and the ability to code pages for that server) or graphics design skills and tools.  All of this made the barrier to adoption quite high. Little content was produced for the wallboards and the content that was produced was of interest to only a few teams, yet it was broadcast to all boards.  Given this, you might think people would get in the habit of ignoring the wallboards.  You would be correct.

We were asked to adopt a new generation wallboard system that could target content by location—from country, to building, to individual board.  That content also needed to be created and maintained by teammates themselves without IT intervention.  Not only did the content need to be dynamic, it also needed to support real-time pushed notifications and any other arbitrary web content, including video streams.

The Solution

We started back down the custom coding route (we are a web company, so no lack for developers), but everybody stays pretty busy with delivering value to our customers across our 20 brands, so finding room in our roadmaps was a real challenge.  We knew we had the 'easy user-created content' problem solved because we had Confluence.  The trick was building or buying a platform for managing and presenting that content.

Then we realized something else: Not only do we have Confluence, but we have a toolset available to us with Bob Swift Atlassian Add-ons that lets us bend Confluence to our will.  We could turn Confluence into a wallboard publication and presentation platform that was more powerful than anything we saw on the market and much easier and faster than building something from the ground up.

The result: HomeAwayTV (we call it HATV around the office).  HATV is a Confluence-based platform that takes user-created content in conventional Confluence pages which is organized by location and wallboard device, and presents it on wallboards with the Confluence UI stripped away so that it is unrecognizable as Confluence on the wallboard, yet has the familiar UI of Confluence for the content creator.  With HATV, we can create content that is targeted and dynamic.  Anything you can do in a Confluence page, you can do on an HATV page, including JIRA Dashboard gadgets, chart macros, embedded videos, and more. 

Not only are the pages dynamic, but we also implemented a real-time banner system that allows us to send out notifications targeted to locations and wallboards as well.  Finally, we implemented a real-time content pusher that let’s us “take over” wallboards with web content.  We stream our weekly all-hands video stream this way by pushing a page with an embedded video stream player to all boards.  When the all-hands is over, one click takes the page down and the boards resume presenting targeted content. 

We built HATV with the following tools (we’ll discuss how we used them further down):

The HATV Framework

HATV is a multi-faceted solution bringing together Confluence native functionality, add-on enhancement, user macros, and some custom code.  In this section, we’ll break down the framework and show how we used a number of tools to get this done.  Later on, we will show HATV in action.

Location-targeted Content

We wanted to target content by location such as Global, Country, State/Province/Region, City, Office (building), as well as individual wallboards.  To do this, we adopted a page naming convention of “context_hero”.  So a page for our Austin HQ office would be named “austinhq_hero”.  Similarly the page for a wallboard in the Austin HQ office might be named “aocmini1234_hero”.  That name could be interpreted as “The page for the wallboard in the Austin Office running on a Mac mini that is nearest cubicle 1234.”  Recognizing that not all contexts would have custom content from the start, we also created default content named by context.  So we had pages named “country_hero”, “city_hero”, etc.

With multiple wallboards in each of 20 offices around the world, this approach called for a lot of pages.  We maintained our sanity by using the Bob Swift Confluence Command Line Interface (CLI) to generate pages from a file containing a list of countries, offices, wallboards, etc.  We created the default pages mentioned above and then, for each context page, we used the CLI to generate a page that had only an Include Page macro referencing the default page.  For example, for each city in which we had an office, the CLI created a page having the name (i.e austin_hero) and content  of “{include page|city_hero}”.

sh confluence.sh --action runFromList –file cities.txt --space WALL  --common "--action addPage --title \"@title@_hero\" --content \"{include page|city_hero}\" --parent Heroes" --continue

In the next section, we will show where that naming convention came in handy.

Dynamically location-targeted (hyper-local) content

On each wallboard, we want to display content that is targeted for it.  We do that by setting the browser home page to a URL with query arguments that identify the location and wallboard info.  So, using our Austin office example:

https://confluenceserver/display/WALL/HATV+Production?Office=austin_office&City=austin&State=texas&Country=united_states&Wallboard=aocmini1234

This breaks down to the Austin HQ wallboard nearest cubicle 1234 which is situated in the city of Austin, the state of Texas, and the country of United States. 

We consume those URL query arguments with the Bob Swift Run Self Service Reports for Confluence add-on.  In the page named “HATV Production,” we have—among other macros—a set of Include Page macros that accept the location values in order to render the page for that location.  To render the city hero for the given city, for example, we have the following macro (in wiki markup): {include:$City_Hero} wrapped by a “Wiki Markup without migration” macro (from the Bob Swift Wiki Markup for Confluence add-on) like so:

We use the Wiki Markup macro because the Include Page macro’s configuration dialog wants to pre-process the arguments so you may preview the result.  In our case, we do not know the argument until runtime as we are providing a token “$City_Hero” that will be pre-processed (using our Austin wallboard example) into “Austin_Hero”.  The result is that the page "HATV Production" will be rendered with the the content of the page “Austin_Hero” included in it.  We do the same thing for the rest of the location values in the URL, as well as for the wallboard name.

Presenting the location content

We present the location-targeted content as a slideshow of the included pages, which rotates in order from global to more localized contexts (country, state, etc) through to the page for the wallboard.  We do this using the ServiceRocket Composition plugin deck of cards macros.  We place an Include Page macro in each card and then have those cards rotate continuously on the page.  A partial representation of that layout looks like this:

Removing the Confluence UI

In order to maximize screen real estate and present the HATV content without the distraction of the unusable UI (unusable because we aren’t connecting keyboards and mice to the TV), we created a user macro that hides all of the Confluence UI.  Called “Kiosk”, it injects some JQuery and CSS into pages to hide the UI.  Here’s a snippet from it:

## Macro title: Kiosk
## Macro has a body: N
## Body processing: unrendered
## Output: html
##
Color|type=string|required=true|desc=Use html color values
<script type="text/javascript">
	if(window.location.search.replace(/.*kiosk=(.).*/,'$1') == "1")
	{
		AJS.toInit(function() {AJS.$(function(){AJS.$("#main-header").css({"display": "none"});});});
…

When the URL parameter “kioskmode” is present with a value of “1”, then the code is injected.  When the argument is missing, the macro is inert and the page renders as expected.

Normal Confluence UI

KioskMode Enabled

Pushing targeted, real-time content

What are we pushing?

To fill out the solution, we need to be able to broadcast (or narrowcast) in real-time, content and notifications targeted just like how the pages for HATV are targeted—to locations, offices, and wallboards.  This means that the content or notifications can be displayed on all wallboards simultaneously (global scope) or to only targeted wallboards such as for a city, an office, etc. 

The notifications are banners that display text on the lower third of the wallboard just like you see on sportscasts and news programs.  They can contain any arbitrary text and be presented in a number of styles.  The rotating targeted pages are still visible except for the small portion obscured by the semi-transparent banner.

The content can be any embeddable web content such as a video player or an external web page.  That content is presented in an Iframe macro that is sized to encompass the entire screen.  Because we strip away the Confluence UI, the web content is also indistinguishable from any other HATV page.  The difference is that while the web content is presented, the other rotating, location-targeted HATV pages are not visible.

How we are pushing it

The HATV wallboard page (“HATV Production” in our illustration above) is only refreshed periodically via a JavaScript timer.  This avoids us having 100+ machines pulling multiple pages 24 hours / day.  In order to push the content on-demand, we use the Pusher Web RTC platform. (Check out the quick start guide for Pusher here.)

The listener

The HATV page has JavaScript inside a Bob Swift HTML for Confluence macro that listens on a Pusher channel for an event fired by the Pusher page that we will discuss in the next section.  That HTML macro is itself encapsulated by a Run Self Service Reports for Confluence macro.  The Run macro allows us to do similar tokenized replacement in the JavaScript as we do in the other macros like Include Page.  In this case, we use the location and wallboard URL query arguments as arguments to the JavaScript so they listen for events only for that wallboard and its location.

Below is a tokenized code snippet for initializing the listener and hooking up to real-time commands for a country:

{html} 
<script src="//js.pusher.com/2.2/pusher.min.js" type="text/javascript"></script> <script type="text/javascript"> 	
AJS.toInit(function(){ 		
var pusher = new Pusher(' Insert Your Pusher Token Here'); 	
var country_stream = pusher.subscribe('$Country _stream'); 	
var country_alert = pusher.subscribe('$Country_alert');
……
country_alert.bind('show', function(data){{Do some JS Here}});
country_alert.bind('hide', function(data) {{Do some JS Here}});
…..
country_stream.bind('show', function(data){{Do some JS Here}});
country_stream.bind('hide', function(data) {{Do some JS Here}});

The JS uses the Pusher library to bind to a socket for the country token value.  There’s a channel for the notification called “alert” and a channel for the web content called “stream”.  We have two commands for each channel—“show” and “hide”—which show and hide the content in the notification or page for the URL given for the web content.  In the JavaScript referred to “Do some JS Here,” we handle the payload of the commands such as text for the notification / alert and do the UI work to present it or withdraw it on the wallboard.

The pusher

Now that we have the page listening for the push notifications, we need to give our users a way to push those notifications out.  Pusher offers a debugger for modeling the calls, but we need to present a friendly UI for doing this.  Once again we call on Bob Swift Run Self Service Reports for Confluence to help us out.  This time we create a form with drop downs for the location values and wallboard names as well the content and commands.  Below is one example where we give the user a UI for showing and hiding notification banners to one or more boards.

Setting aside how to build the form (which is well documented here), let’s look at how we push the command for the Listener to pick up (more Bob Swift goodness ahead):

We take the values from the form to tokenize the arguments to a Groovy script (embedded in a Bob Swift Scripting for Confluence macro which is embedded in a Bob Swift Wiki Markup for Confluence macro) that uses a Pusher Groovy library to make the call to Pusher given the channel, the action (command) and the payload.  The Groovy script triggers the event for which the JavaScript we looked at earlier is listening.

And that’s not all

There’s a lot more code and technique that we aren’t covering here. However, we have covered a solid example of each of the techniques and patterns we used.  In the next section we’ll take a quick look at how we rolled out HATV and what it has done for us.

The rollout

How we deployed HATV

We have Mac Mini and Intel Compute Stick powered TVs with Google Chrome in presentation mode having a home page URL containing query parameters to drive the Run Self-Service Reports macro tokenization arguments as well as the Confluence chrome suppression macro.

The User Experience in HATV

  • User requests permission to curate content for a specific context (such as the content broadcast to all offices in Austin).  Permission is granted via page permissions.
  • User creates content on the page just as they would for any other page, with the exception that they scale the content for 50+ inch 1080p screens.  Once saved, the page is live on HATV.
  • Any wallboard can be simulated by using a Run Self Service Reports macro-powered page that enables the user to select the "channels" (locations and wallboards) to render the Confluence page as it will appear on the wallboard configured for those channels.

The Results (just a few)

  • HR teams are leveraging HATV as a powerful broadcasting complement to conventional Confluence pages, blogs, emails, and paper flyers.
  • Customer Service publishes real-time call queue data and customer satisfaction analytics to their team.
  • Network Operations monitors critical ops data and publishes real-time alerts to affected users.
  • Dev teams publishes JIRA Agile gadgets, build status, and real-time prod stats from HA sites (# of Shopping Cart transactions, # of Rental Inquiries, etc.).
  • All-hands live video is streamed globally to HATV wallboards with one click.

What have we learned?

Firstly: Bob Swift is our hero.  He’s probably yours too!

Secondly, thirdly, fourthly, etc: We learned that Confluence is an incredibly robust platform for collaboration and communication in the enterprise.  A big reason for that robustness is the plugin architecture and the healthy and steadily growing marketplace for add-ons that exploit the plugin architecture.  

The Bob Swift Atlassian Add-ons really show off what can be done as an add-on developer and what an admin can do with the right set of add-ons.  Hopefully you’ve seen some things that inspire you to super-power Confluence in your organization.  We’d love to hear about them in the comments.

 

 

Ready for JIRA 7.0

Atlassian has just released the new JIRA product family based on JIRA Core 7.0. This is a major advancement for the JIRA product line. For the past few months, we have been upgrading and testing our products to work with JIRA 7.0. All add-ons have been successfully tested on JIRA 7.0 final. 

 

Versions marked as SNAPSHOT will be released soon. Watch this page for updates.

JIRA CLI

The JIRA CLI client 4.5 was built to support JIRA Cloud using JIRA 7.0, there are a few things that are broken with JIRA Server 7.0. These are resolved with the JIRA CLI 5.0. This is recommend when working with JIRA 7.0 instances.