The Reflect Interactions API

Build customized data interactions into your Reflect views.

From the very beginning, one of our highest priorities here at Reflect has been to provide our users with data visualizations that are beautiful, powerful, and intuitive yet require almost no engineering resources. We call this basic embedding, which lets you embed a Reflect view on a page by essentially copying and pasting some simple HTML and JavaScript, much like you would for, say, Google Analytics or Segment.

But we know developers (we are developers!) and we know that getting up and running quickly isn’t always the end goal. Sometimes, building a compelling, interactive experience around data means building something that is less “out of the box” and much more tailored to the end user. So we’re also building a variety of features into Reflect that enable developers to create highly customized views.

The first of these features is the Reflect Interactions API, which allows you to build interactive experiences around your data with just a little bit of JavaScript.

Check out the Reflect docs

For instructions on using Reflect views in your applications, see our guide to embedding views. For more specific docs on the Interactions API, see the Interactions section of that page.

How it works

Each Reflect view (or dashboard, if your prefer), is made up of any number of visualization components. Reflect currently offers five types of components.

See examples of each component type

In case you haven’t seen our various components in action, see the links below for some samples:

Each component in your views is given a slug, such as your-timeseries-component-1, which enables you to create custom interactions that apply only to that specific component. You can also combine any number of component types together into a multi-component view.

Embedding Reflect views

To embed any Reflect view in your application, you need to create a ReflectUI object for that view, apply configuration to the view (optional), and finally call a view function that specifies the project slug, the view slug, and DOM element you’re targeting:

var reflectView = new ReflectUI('a1b2c3d-your-secure-api-token-4e5f6g7');

// Configure the view here

reflectView.view(
  document.getElementById('your-view-container'),
  'your-project',
  'your-view'
);

The more interesting part for our purposes here is what goes in the middle. This is where you can do all kinds of things with Reflect views, from applying custom field formatters to setting custom view parameters to using the Interactions API. Here’s a custom interactions example:

reflectView.on('your-component-slug', 'event-type', function(data) {
  // Do something with the data emitted by the event
});

The on function takes three arguments:

  • The slug of the component you want to target
  • The event type for which you want to create the custom interaction
  • The callback function that does something with the data emitted by the event

What kinds of things can you do inside of that callback function? That’s totally up to you. We’ve included some examples below.

Event types

The interaction events that are available for customization differ based on the component type. For timeseries components, for example, there are three event types available:

Event Emitted after…
dataPointClick A user clicks on a specific data point
legendItemClick A user clicks on an item in the timeseries component’s legend
render The component has successfully rendered

Consult our documentation to see which event types are available for other component types.

Interactions versus other customizations

The difference between custom interactions and, say, custom formatters or custom parameters for views is that interactions capture the actual data associated with what you click.

In the examples below, we’ll be working with the dataPointClick event type, which handles data associated with clicking on a specific data point. JSON objects emitted by dataPointClick events contain three keys that you can use in your callback function:

Key Data type Value
event MouseEvent The click event that triggered the interaction
field object The data field used by the component
rowData object The data associated with the point; the structure of this object will depend on the component type and data model

Other event types emit data objects with different structures. Check out our docs for info on other event types.

Simple example: displaying the value of a data point

To give a very basic taste of what a custom interaction can look like, imagine that you want to enable users to see what value is associated with each data point in a timeseries visualization by clicking on the point.

One way to implement that might be to enable jQuery on your site and place an empty div component with the ID your-div-element on the page housing your Reflect view. Your custom interaction could capture the data from any timeseries data point that is clicked and then populate that div with the JSON value from the data point:

<div id="your-div-element"></div>

<script type="text/javascript">
  var reflectView = new ReflectUI('a1b2c3d-your-secure-api-token-4e5f6g7');

  reflectView.on('example-timeseries-component', 'dataPointClick', function(data) {
    $('#your-div-element').text(JSON.stringify(data.rowData));
  });

  reflectView.view(
    document.getElementById('view-container'),
    'your-project',
    'your-view'
  );
</script>

The visualization below provides a real-life illustration. If you click on any of the data points in this timeseries component, the data associated with that point will be displayed immediately below the component:

In a real-world use case, that per-point data could be, for example, piped to a metrics database used for analyzing user preferences, added to the user’s session data, you name it. It’s up to you.

Check it out on CodePen

See the Pen Reflect Interactions API Example by Reflect (@reflect) on CodePen.

More complex example: drilling down into data

In the simple example above, we didn’t actually do anything with the data captured by the dataPointClick event beyond simply displaying it. Now that we’ve gotten our hands dirty, let’s do something a bit more snazzy. In the visualization below, click on one of the arcs in the donut. When you do that, the timeseries component will show the total sales for that specific customer segment over the past two weeks:

How it works

In order to make this happen, I created one view with two components using Reflect app: a donut showing percentage of total sales (metric) by customer segment (dimension) and a timeseries showing sales over time within that segment.

All I need to do in the HTML is to import Reflect’s JavaScript and CSS and add a div element and a script to hold some JavaScript:

<head>
  <link rel="stylesheet" href="https://cdn.reflect.io/0.4.0/reflect.css" />
  <script type="text/javascript" src="https://cdn.reflect.io/0.4.0/reflect.js" charset="UTF-8"></script>
</head>
<body>
  <div id="drilldown-container"></div>

  <script type="text/javascript">
    // See code sample below
  </script>
</body>

The JavaScript needs to accomplish each of the following:

  1. Render the initial donut view
  2. Capture data from each pie chart arc when you click on it
  3. Use that data to add a filter to the timeseries component through an override
  4. Use a view override to create a custom title for the timeseries view each time it’s rendered (e.g. “Corporate Sales Over Time,” “Consumer Sales Over Time,” etc.)

Here’s some example JavaScript that accomplishes all of the above (don’t forget to read the comments!):

// Create a UI object using an API token fetched from https://app.reflect.io
var reflectUi = new ReflectUI('a1b2c3d-your-secure-api-token-4e5f6g7');

// Render the initial donut view
reflectUi.view(
  document.getElementById('drilldown-container'),
  'my-example-project', // Project slug
  'drilldown-example' // View slug
);

// Specify interaction logic for when a data point on the donut is clicked
reflectUi.on('donut', 'dataPointClick', function(data) {
  // Get the name of the customer segment from the data object
  var customerSegment = data.rowData['Customer Segment'];

  // Specify the title of the timeseries view using an override
  reflectUi.withOverrides([
    {
      slug: 'timeseries-drilldown',
      path: 'title',
      value: customerSegment + ' Sales Over Time'
    },
    {
      slug: 'timeseries-drilldown',
      path: 'filters',
      value: [
        {
          field: 'Customer Segment',
          op: '=',
          value: customerSegment
        }
      ]
    }
  ]);

  // Re-render the view
  reflectUi.view(
    document.getElementById('drilldown-container'),
    'my-example-project',
    'drilldown-example'
  );
});

And that’s it! In just a few dozen lines of code we were able to produce a highly intuitive drilldown visualization that tells a multi-faceted story using data.

Check it out on CodePen

See the Pen Reflect Interactions API Drilldown Example by Reflect (@reflect) on CodePen.

Conclusion

We believe that good visualization software, like most software, should provide a powerful, intuitive experience that doesn’t require a lot of up-front effort, and we’ve strived to provide that in Reflect views. But we also know that developers very often want the freedom to provide their own non-default functionality and to delight their users in ways that we couldn’t have envisioned.

Our interactions API is the first of many avenues that we plan to provide that enable precisely this, with others on the way (stay tuned for things like custom themes and much more).