Display a Dynamic, Interactive D3.js Visualization on GitHub Pages

Interactive D3.js Visualization

GitHub Pages is a great place to build and publish a website quickly, and you can host a site directly from your GitHub repository. However, because GitHub Pages doesn’t support server-side code, you can’t display interactive data visualizations and other dynamic content using a traditional server-based approach.

A simple solution to this limitation is to switch to an API-driven approach using a data pipe. Here’s how you can add an interactive data visualizations to a website hosted on GitHub pages.

Demo

The visualization we’re using here is a Bubble Chart word cloud, with thanks to Mike Bostock and D3.js.

bubble chart

You can play around with a live version hosted from our examples repository on GitHub.

Setup

The setup here is geared to hosting the data visualization on GitHub Pages, but the steps involved are basically the same for any website.

1. Create a GitHub repository for the website

Create a new GitHub repo for the website that will display the bubble chart. Skip this step if you already have one.

2. Add the website code to an index.html file in a new GitHub repo

You can find the source code for the front end components here. Copy this code into an index.html file in the master branch of the GitHub repo you’ve set up.

A quick way to do this is to view and copy a raw version of the source code, click the Create new file button in your GitHub repository to add index.html, and then paste this code directly into the empty Edit new file box:

Add a new file to GitHub repository

3. Grab a copy of the data pipe

Visit the template page for the data pipe, and grab a copy. Click the Use This Pipe button to copy the pipe into your own account.

Add D3 Chart to GitHub Page

For this step, you’ll need to have a Flex.io account. You can sign up for a free account here, if you don’t have one already.

4. Configure the alias for data pipe

In order run the data pipe via an API call, you need to give it an alias. To do this, click on the Add an alias button to the right of the pipe name at the top and then type in the new alias you want to use.

Add Pipe Alias

Generally, it’s best to prefix your alias with your username. For this example, let’s use foo-bubble-chart-on-static-page-example.

5. Add an API key to your account

In order for a pipe to be referenced via an API call, you’ll need to set up an API key in your Flex.io account, if you don’t have one already. To do this, go to your account area, select the API tab and click the Create API Key button.

Flex.io Create API key

6. Update the API call in the website code with the new alias and API key

Now that you have everything set with the API key and pipe alias, you can update the code for the website with these values. This will switch over the API call to run the pipe you just set up in your account.

The parts you need to change are the URL on line 216 and the API key on line 218:

$.ajax({
type: 'post',
url: 'https://www.flex.io/api/v1/pipes/flexio-text-keywords-v1/run?stream=0',
beforeSend: function(xhr) {
xhr.setRequestHeader('Authorization', 'Bearer nmgzsqppgwqbvkfhjdjd');
},
...
})

For the URL, change the value after /pipes/ to the new alias for your pipe (e.g., foo-bubble-chart-on-static-page-example):

url: 'https://www.flex.io/api/v1/pipes/foo-bubble-chart-on-static-page-example/run?stream=0',

For the API key, swap out the value after Bearer with the API key you set up for your account:

xhr.setRequestHeader('Authorization', 'Bearer yourapikeygoeshere');

7. Publish the website on GitHub Pages

At this point, everything is set. The only remaining step is to update the settings for your GitHub repository to publish the website.

To do this, select the Settings tab in GitHub, scroll down to the GitHub Pages section and update Source to “master branch”:

Publish a website from a GitHub repository

Assuming you’ve added the index.html file to the master branch of the repository, when you navigate the web address GitHub provides for this page (typically https://githubaccountname.github.io/repositoryname), you’ll see a live, working version of an interactive data visualization.

How it Works

On the front end, there are two interface controls that update the bubble chart dynamically.

Text Entry Box for the Website URL

The bubble chart is set up to show the frequency of key words found on a particular web page, based on the web address a user enters:

url entry box

Slider Component

The slider control allows users to select the miniumum and maximum word count that the bubble chart displays, providing a simple way to explore the data interactively. This example uses the Ion.Rangeslider slider component for this control, along with a few CSS modifications to simplify the presentation:

slider control

There are three variables associated with these interface components, defined as ‘url’, ‘min_threshold’ and ‘max_threshold’ in the HTML code:

<form class="mt3 mb2">
<div class="f5 dib pr1">Enter URL:</div>
<input id="input_url" class="input-reset ba b--black-20 pa2 f6 w5" style="width: 400px" name="url" placeholder='"https://www.flex.io", etc.'>
<button type="button" class="btn-submit border-box no-select ba ttu b f6 ph3 pv2 br1 white bg-blue b--blue darken-10">Submit</button>
<input id="input_min" type="hidden" name="min_threshold" value="0">
<input id="input_max" type="hidden" name="max_threshold" value="100000">
</form>

These variables are passed as parameters to the data pipe via an API call.

API Call

On the back end, all of the work to generate the values for the bubble chart is done by a Flex.io data pipe, which is invoked with a single API call:

type: 'post',
url: 'https://www.flex.io/api/v1/pipes/flexio-text-keywords-v1/run?stream=0',

The API call is made within an AJAX request so that when the user updates any of the interface controls, the data pipe automatically generates a new set of values for the bubble chart:

$.ajax({
type: 'post',
url: 'https://www.flex.io/api/v1/pipes/flexio-text-keywords-v1/run?stream=0',
beforeSend: function(xhr) {
xhr.setRequestHeader('Authorization', 'Bearer nmgzsqppgwqbvkfhjdjd');
},
data: $('form').serialize(),
dataType: "json",
success: function (content) {
updateMinMax(content);
updateSvg(content);
// enable submit button
$('.btn-submit').removeClass('o-40').text('Submit').removeAttr('disabled');
$('#top').removeClass('loading');
},
error: function (xhr, status, error) {
alert('post failed');
}
});