ANNOUNCEMENT We're excited to announce that we've been acquired by Puppet! More information in our blog.

company/logos/logo-color.svg Menu

How to embed your visualizations

Use Reflect.js to configure and display Reflect views in your applications

Once you’re happy with the views you’ve built, the last step is to embed them into your app. This document outlines the steps to do so using our JavaScript library, Reflect.js. We also go into detail on the various customizations you can make to your embedded views at runtime.

You can also embed views using one of our JavaScript framework libraries:

Embedding

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

  <script type="text/javascript">
    var reflect = new ReflectUI();
    var element = document.getElementById('your-view-container');
    var view = 'Samp13View1D';

    reflect.view(view)
      .render(element)
  </script>
</body>

The first step is to initialize a ReflectUI instance, which allows you to configure and render your various views. From there, you can configure it however you’d like.

Next you’ll need to register your view by providing your view identifier:

new ReflectUI().view('Samp13View1D');

The last step is to render that view. You’ll need to tell the ReflectUI client where on the page you’d like it rendered, like so:

new ReflectUI().view('Samp13View1D')
  .render(document.getElementById('your-view-container'));

Try it

See the Pen Reflect Embedding by Reflect (@reflect) on CodePen.

Customizing your Reflect views

Reflect.js enables you to customize your Reflect views in a variety of ways, including:

Each of the sections below assumes that you’ve instantiated a ReflectUI client called reflect that will later call the view() function:

var reflect = new ReflectUI(),
var element = document.getElementById('your-view-container'),
var view = 'Samp13View1D';

// Customize your view using the reflect object

reflect.view(view);

Exporting

In addition to rendering your views, Reflect.js allows you to export them as a PDF, redirecting your user to download the file. Reflect.js takes care of all the steps for you, such as generating the export, waiting for it to finish, then redirecting your user.

new ReflectUI().view('Samp13View1D')
  .export()

Filters

Filters enable you to break down a report by a specific field. You can add filters to a Reflect view using the withFilters() method. This is useful if your app has existing filter controls or if you want to build in drilldown functionality. Here’s an example:

var alexNameFilter = {
  field: 'Name',
  op: '=',
  value: 'Alex'
}

reflect.withFilters([
  alexNameFilter
]);

Filters can be changed by users

Because filters are provided client-side, they can be modified by potentially malicious users. If you need to securely filter your data (for example, to provide multitenancy), you’ll want to use authentication tokens instead.

Formatters

Reflect enables you to format field values using either your own custom JavaScript functions or functions supplied by Reflect. Custom formatting enables you to have explicit control over the appearance of your labels. For example, formatters could be used to:

  • display the value of an Efficiency field as 80% rather than a raw value of 0.8
  • display a Date field’s value as February 6, 1960 rather than 2-6-1960
  • render an image instead of displaying a raw image URL

Custom formatters override default

If you apply a custom formatter to a label using withFormatters(), this will override any default formatter applied to the label.

Custom formatter functions

Formatter functions take a field’s value as an input and return a string. Here’s a basic formatter that adds an exclamation point to a string field’s value:

function exclaim(s) {
  return s + '!';
}

To apply that formatter to a field called Statement in a view:

reflect.withFormatters({
  'Statement': exclaim
});

You can apply formatters to as many fields as you like:

reflect.withFormatters({
  'Revenue': /* formatter */,
  'Losses': /* formatter */,
  'Interest': /* formatter */
});

Available formatters

Reflect provides a variety of formatters out of the box that you can use in your own views. You can use them by passing the name of the formatter as a string instead of a function. Here’s an example:

reflect.withFormatters({
  'Revenue': 'dollars',
  'Time of Purchase': 'date',
  'Sales tax': 'percentage'
});

Mix and match custom and Reflect-provided formatters

Using the formatters listed in the table below does not preclude you from providing your own formatters alongside the ones that Reflect provides.

The table below lists the available formatters:

Name Transformation Example in Example out
percentage Multiply a numeric field by 100 and display it as a percentage 0.97 97%
percent_change Express the delta between two numeric field values as a percentage [1, 5] 80.00%
numeric_percentage Display a numeric value as a percentage without multiplying by 100 0.25 0.25%
dollars Display a numeric value as a dollar currency figure 100.125 $100.13
numeric Display a numeric value with no decimal places 300.13 300
month Display only the month (in English) and year value from a timestamp 2015-01-01 12:15:00-07:00 January 2015
date Display a timestamp as MM/DD/YYYY 2015-01-01 12:15:00-07:00 01/01/2015
date_with_hour Display a timestamp as MM/DD/YYYY hh:00 A 2015-01-01 12:15:00-07:00 01/01/2015 12:00 PM
date_with_time Display a timestamp as MM/DD/YYYY hh:mm A 2015-01-01 12:15:00-07:00 01/01/2015 12:15 PM
lowercase Convert a string field value to lowercase TeEnSy teensy
uppercase Convert a string field value to uppercase enormous ENORMOUS
titleize Converts a string to title format i_love_reflect I Love Reflect
true_or_false Converts a 0-or-1 field value to false or true 0 / 1 false / true
yes_or_no Converts a 0-or-1 field value to no or yes 0 / 1 no / yes
web_content Within a string field, find all the URLs and convert them to hyperlinks Check out https://reflect.io Check out https://reflect.io
image Turn a string field into an image http://goo.gl/a5k3i9 Rickrolled

Date ranges

In Reflect views that include a date field, you can use the withDates() function to programmatically set a date range, perhaps in response to user input. You can use custom date ranges in cases where you want to, for example, supply your own custom datepicker.

Setting a date range overrides user input

If you have a datepicker enabled for the view, setting a date range using withDates() will overwrite any range that the user selects. If you want to supply your own datepicker or allow users to select a date range otherwise, you’ll need to disable the Reflect datepicker on the view.

You can apply a date range in one of two ways:

  • By passing a single date range as a two-member array to withDates()
  • By passing two date arrays, which will compare the two ranges

Here’s an example of passing a single date range:

var dateRangeFor2015 = ['2015-01-01', '2016-01-01'];

reflect.withDates(dateRangeFor2015);

Here’s an example that compares two ranges:

var dateRangeFor2014 = ['2014-01-01', '2015-01-01'];

reflect.withDates(dateRangeFor2014, dateRangeFor2015);

Timezones

The withTimezone() function allows you to programmatically change the timezone that Reflect presents data in. When data is aggregated for a visualization, it will be aggregated in the supplied timezone. When a date is presented to the user as part of a visualization, it will be converted in to the supplied timezone.

reflect.withTimezone('America/Los_Angeles');

Timezone supplied automatically

If no timezone is supplied, Reflect will automatically infer the timezone based on the user’s browser settings.

The withTimezone() function accepts any timezone listed in the IANA zoneinfo database.

Overrides

Whether you create a Reflect view in the Reflect app or over our REST API, you may want to modify the behavior and other aspects of your view at runtime. You can use the withOverrides() function to override any field in the JSON object that defines a view’s configuration (also known as a view manifest).

For a full list of configurable fields for views, see our REST API docs.

Overrides are all powerful, but only use them when necessary

You can apply an override to any field in the view manifest that defines a view. Any of the view modifications mentioned in this doc, including filters, interactions, and date ranges, can be applied using withOverrides(). In general, however, you should use overrides only in cases when there’s no other way to modify the view. You should not add, for example, custom filters this way, as there’s already a well-defined interface for this.

For a full listing of configuration options available for views, see our REST API docs.

All Reflect overrides are JavaScript objects with two fields:

Name Description
slug or path Either the slug of the component you wish to target or a JSONPath pointing to the key in the view configuration that you wish to target
value The value you wish to set for the component and key

As mentioned in the table above, there are two ways that you can target view manifest keys for overrides:

  1. If the field is outside the components array of the view manifest object, you can use JSONPath to specify a path and assign a value using value. Here’s an example:

    var jsonPathOverride = {
      path: '$.field.subfield.subsubfield',
      value: 'this is an override value'
    }
    
    reflect.withOverrides([
      jsonPathOverride
    ]);
    
  2. If a field is inside of the components array of the view manifest object, you can target the field by specifying a component slug using slug and a JSONPath using path; the override value can be assigned using value. Here’s an example override that changes the title of a component to My Component at runtime, no matter how the title is specified in the view manifest:

    var componentSlugOverride = {
      slug: 'your-component',
      path: 'title',
      value: 'this is an override title'
    }
    
    reflect.withOverrides([
      componentSlugOverride
    ]);
    

These two override objects, for example, target keys in different ways but ultimately apply the same override:

var titleOverrideViaJsonPath = {
  path: '$components.[0].title',
  value: 'Overridden Title'
}

var titleOverrideViaComponentSlug = {
  slug: 'timeseries-component-1',
  path: 'title',
  value: 'Overridden Title'
}

Interactions

Reflect’s Interactions API enables you to build rich interactive experiences into Reflect views by specifying custom behavior for a wide variety of events.

The Interactions API versus other customizations

The core difference between the Interactions API and other ways of customizing Reflect views is that interactions emit the underlying data associated with an event, which you can then manipulate any way you’d like inside of a callback.

Enabling interactions

By default, custom interactions are disabled for all component types. You can enable custom interactions for a component in the Reflect app in the Events field, which looks like this:

reflect-studio/snippets/enable-events.png

Different component types have different customizable interaction types associated with them, and you can selectively enable and disable them one by one.

Basic interaction logic

You can add a custom interaction to a Reflect view (provided that the interaction has been enabled) using an on function that 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 handles the data emitted by the event

Here’s a generic example:

reflect.on('some-component-slug', 'someEventType', function(data) {
  // Handle the data passed to the callback
});

Here’s a more specific example that prints data emitted by a dataPointClick event to the console:

reflect.on('your-reflect-component', 'dataPointClick', function(data) {
  console.log('The following data was emitted by the click event:');
  console.log(data);
});

Interaction types

Each Reflect component type has various events that can be configured for components of its type.

Name Emitted after… Components
render The component is rendered All components
dataPointClick A user clicks on a specific data point Timeseries, Donut, Bars, Area, Line
legendItemClick A user clicks on a value in a legend Timeseries, Donut, Bars, Area, Line
tableCellClick A user clicks on a cell Datagrid
componentClick A user clicks anywhere on the component KPI
annotationClick A user clicks on an annotation that has been enabled on a component All components

Event types

All interaction events belong to one of a handful of event types (described in detail in the sections below). Each event type emits objects of a defined structure.

render

Events of type render are fired after a visualization component has rendered. Data objects emitted by render events have the following fields:

Name Type Description
title string The title of the visualization component
dimensions object The dimensions of the component
group object The group of the component
metrics object A metrics object

Here’s an example object emitted by a render event:

var data = {
  title: "Productivity by Name"
  dimensions: [{ name: 'Date' }],
  group: [{ name: 'Date' }],
  metrics: [{ name: 'Productivity' }, { name: 'Software Development Time' }, { name: 'Hours Logged' }],
};

dataPointClick

Events of type dataPointClick are fired after a user clicks on a specific data point in a visualization. Data objects emitted by dataPointClick events have the following fields:

Name Type Description
event MouseEvent The click event itself
field string The field that was clicked on
rowData object Field names and values for the entire row

Here’s an example object emitted by a dataPointClick event:

var data = {
  event: MouseEvent,
  field: 'Name',
  rowData: {
    'Name': 'Alex',
    'Birthday': '08-03-1942',
    'Employer': 'Reflect'
  }
};

legendItemClick

Events of type legendItemClick are fired after a user clicks on a value in a legend. Data objects emitted by legendItemClick events have the following fields:

Name Type Description
event MouseEvent The click event itself
field string The dimension the legend is displaying
value string The value that was clicked on

Here’s an example object emitted by a legendItemClick event:

var data = {
  event: MouseEvent,
  field: 'Name',
  value: 'Alex'
};

componentClick

Events of type componentClick are fired after a user clicks anywhere on the component. Data objects emitted by componentClick events have the following field:

Name Type Description
event MouseEvent The click event itself

Here’s an example object emitted by a componentClick event:

var data = {
  event: MouseEvent
};

annotationClick

Events of type AnnotationClick are fired after a user clicks on an annotation that has been enabled on the component. Data objects emitted by annotationClick events have the following fields:

Name Type Description
event MouseEvent The click event itself
field string The field the annotation has been enabled on
rowData object Field names and values for the entire row the annotation is displayed on

Here’s an example object emitted by an annotationClick event:

var data = {
  event: MouseEvent,
  field: 'Orders',
  rowData: {
    Orders: 5,
    Region: 'West',
  },
};

Control components

In addition to the five visualization component types offered by Reflect, there are two control components whose behavior you can also customize:

  • The filter bar enables users to apply filters to a view. You can use the Interactions API to control what happens when filters are added or removed.
  • The datepicker enables users to select date ranges that apply to an entire view. You can use the Interactions API to control what happens when a user changes the date range in the datepicker.

When creating custom interactions for control components, you need to use an identifier for the component instead of a slug: filter for the filter bar and datePicker for the datepicker.

Filter bar events

There are two types of event that can be triggered by a filter bar:

Name Fired after…
addFilter A user adds a filter
removeFilter A user removes a filter

When you add or remove a filter, an object is emitted that has two fields:

Name Type Description
action string Currently either add or remove
filter object The filter object that has been added or removed. See Filters for more info on filter objects.

Here’s an example object emitted when a user adds a filter:

var data = {
  action: 'add',
  filter: { field: 'Field name', op: '=', value: 'Field value' }
}

Here’s an example filter bar interaction:

reflect.on('filters', 'addFilter', function(data) {
  console.log('A filter has been added for the following field: ' + data.filter.field);
});

Datepicker

There is just one type of event that can be triggered by a datepicker:

Name Fired after…
dateRangeChange A user changes the date range specified by the datepicker

When a datepicker’s date range is changed, an object is emitted that is simply an array with two values: the new start date and the new end date. Here’s an example: ['11-01-2017', '11-09-2017'].

Here’s an example datepicker interaction:

reflect.on('datePicker', 'dateRangeChange', function(dates) {
  var startDate = dates[0],
      endDate   = dates[1];
  console.log('The new date range begins with ' + startDate + ' and ends with ' + endDate);
});

Interaction API examples

You can see two Interaction API examples in action on CodePen.

This simpler example shows data being emitted by dataPointClick events and piped into a DOM element for viewing:

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


This more complex example shows a donut component whose arcs can be clicked to reveal a timeseries component that drills down into a selected customer segment:

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

Custom colors

You can specify custom colors for values of dimension fields using the withColors() function. You can pass an object to that function in which the keys are names of fields in your view and the values are objects that map specific field values to specific HTML color codes.

If one of your views had a dimension field called Name and you wanted to associate the color #aeea00 (lime green) with the value Julia, you could do so like this:

reflect.withColors({
  'Name': {
    'Julia': '#aeea00'
  }
});

If you don’t specify custom colors, Reflect.js will assign default colors. See our Visualization doc for examples. Here’s a component that uses Reflect’s default colors:

Now imagine that Google were a Reflect user and wanted to create a Reflect view that matches their company branding. They could use custom colors to create a view that looks like the one below instead of this:

Here’s the corresponding JavaScript for that view:

reflect.withColors({
  'Customer Segment': {
    'Corporate': '#00a1f1',
    'Home Office': '#7cbb00',
    'Consumer': '#ffbb00',
    'Small Business': '#f65314'
  }
});

And finally, just for fun, here’s the same component with a Solarized Dark theme:

And here’s the JavaScript for that view:

reflect.withColors({
  'Customer Segment': {
    'Corporate': '#073642',
    'Home Office': '#586e75',
    'Consumer': '#2aa198',
    'Small Business': '#d33682'
  }
});

Custom colors with Datagrids

Custom colors can be applied to datagrids as well.

In addition to the interface used for defining colors on other components, datagrids support conditional styling through callback functions.

Specifying a string as the color will set the text color. Returning an object with camelCased keys will set other style attributes on the text. Examples include background, fontWeight, etc.

And here’s the JavaScript for that view:

reflect.withColors({
  'Region': {
    'West': { fontWeight: 'bold' },
  },
  'Sales': function(rowData) {
    if (rowData['Sales'] <= 1000000) {
      return 'blue';
    }
  },
  'Total Sales': function(rowData) {
    if (rowData['Sales'] <= 1000000) {
      return 'red';
    }
  }
});

Custom colors and formatters

always be sure to specify the unformatted values when using custom colors.

Custom labels

Some datasets require that data be ordered in a specific way that you can’t easily accomplish with sorting. The best example here is if your data contains days or months: neither of which you can reasonably sort alphabetically.

For the example of days, not only do you want to order your days the way they occur throughout the week, you also want to make sure all of them are included. This is what labels are for.

By using our API to set a labels attribute on your component, you can specify how the dimensional values should be presented.

And here’s the labels for that component:

"labels": {
  "Day of week": [
    "sun",
    "mon",
    "tue",
    "wed",
    "thu",
    "fri",
    "sat"
  ]
},

Labels and formatters

Much like custom colors, always be sure to specify the unformatted values when using labels.

Currently, we do not offer a way to specify these at embed time.

Custom component types

Custom component types are in private beta

Custom component types are currently in private beta. For more information or to get a demo, please contact support@reflect.io.

Custom component types allow you to write custom JavaScript to render your own visualizations within a Reflect view. This allows you to use Chart.js, D3, Highcharts or any other charting library that can render charts to the DOM. If you’ve connected Reflect to a dataset containing geographic data, you can even use mapping libraries like Leaflet or Google Maps to visualize your data on top of a map.

Since they’re integrated into your reflect view, custom components work seamlessly with the Reflect view controls you’re used to such as the date picker, filter bar, and dimension/metric/group pickers. This provides a consistent way for your users to interact with your data– whether you’re using Reflect charts or your own.

Example

Below is an example of a view with a Timeseries chart and a custom component, built using Leaflet and leaflet-heatmap. If you try adding filters or changing the date range, you’ll notice that both the map and the Timeseries react to your changes.

You can also find an expanded version of this example here.

How it works

As mentioned, custom chart types are simple JavaScript callbacks you provide to Reflect.js. After Reflect.js has queried the Reflect API for the relevant data, it will invoke your callback with the data, the chart settings (title, etc), as well as a DOM element that you should render to. Every time the view is manipulated by the user (via adding a filter, changing date range, etc.) your callback will be again invoked with the relevant arguments.

reflect.withChartTypes({
  heatmap: function(elememt, settings, data) {
    element.innerHTML = "I'm a custom component type!"
  }
});

Accessing analytics data

ReflectUI has a function that gives you access directly to your analytics data. You can use it to integrate analytics data anywhere in your app.

The report function lets you specify which data model to use, which metrics and dimensions you want to report on, and gives you access to a collection of options that might be useful for your data.

reflect.report(project_slug, dimensions, metrics, options);

The function returns a promise that will be populated with the results from the Reflect API.

Example

Below is an example of how to use the report function on ReflectUI to get analytics data to use elsewhere in your app.

var reflect = new ReflectUI('a1b2c3d-your-readonly-api-token-4e5f6g7'),
    dimensions = ['Order Date'],
    metrics = ['Total Orders'];

// Example filters to apply to the report.
var filters = [
  { "field": "Order Date", "op": ">=", "value": "2018-02-27" },
  { "field": "Order Date", "op": "<=", "value": "2018-03-21" }
];

// Example options that we want to send (e.g. filters)
var options = {
  filters: filters
};

reflect.report('order-data', dimensions, metrics, options).then(function(response) {
  console.log('Settings used:', response.settings);
  console.log('Results:', response.results);
});