Reports

Working with reports in code is done by using a Report object. A Report object can be used in a few days:

  • Supplied directly to a Chart for visualization:
    <Chart data={data.reportObject} />
  • Report data retrieved via the JS API:
    const reportData = await ReportData.get(reportObject);
  • As data source for report plugins:
    const forecast = await PluginData.get("plugins/forecast", {
    data: reportObject,
    params: ...
    });
note

Reports cannot be retrieved in parallel at the moment, but this will be fixed in the near future.

If you have multiple <Chart data={"abcd-1234"}> or <Chart data={reportObject}> or use Promise.all, you have to get the data 1-by-1 sequentially instead using the following workaround:

JS code:
const reportData1 = await ReportData.get('abcd-1234');
const reportData2 = await ReportData.get(reportObject);
return {reportData1, reportData2};
JSX code:
<Insight>
<Chart data={data.reportData1} />
<Chart data={data.reportData2} />
</Insight>

Report bookmarks

The easiest way to work with Reports that involves as little code as possible is to make one from the UI first. Use the Custom Report option from the Custom top menu. Once the report results are in, bookmark the report.

Because report bookmarks also work with Template Variables, end-users can change the questions and those changes will be reflected when you retrieve or use the bookmarked report.

To get the bookmark ID for your report, edit your Insight and use the Example Code dropdown to select the bookmarked report, and then copy the bookmark ID string.

Once you have the bookmark ID you can use it anywhere instead of a Report object:

  • Supplied directly to a Chart for visualization:
    <Chart data="abcd-12345" />
  • Get the Report object:
    const reportObject = await Report.getBookmark("abcd-12345");
    const reportData = await ReportData.get(reportObject);
  • Report data retrieved via the JS API:
    const reportData = await ReportData.get("abcd-12345");
  • As data source for report plugins:
    const forecast = await PluginData.get("plugins/forecast", {
    data: "abcd-12345",
    params: ...
    });

Report objects

Another way to work with reports is to use Report objects directly. This has the advantage that you can dynamically build your report based on user inputs or report/plugin results:

const reportObject = new Report({
reportType: "funnel",
timeUnit: "total",
dateRanges: ["LAST_180_DAYS"],
events: ["landing_page", "add_to_cart", "paid"]
});
reportObject.addGroupBy({table: "users", property: "u_col_initial_country"});

The reportObject can then be used as shown in the examples at the top of this page.

For recipes and details working with the report object, such as specific reports, date ranges, custom SQL and more the API-Library for the Report class.

tip

An easy way to construct a Report object is to run a non-standalone Insight on top of any report you've made from the UI. Then use the Debug component show the raw report object like this, which can then be fully copy-pasted as-is:

Make non-standalone Insight to display raw report object:
<Insight>
<Debug obj={report} />
</Insight>
Use copied raw report object:
const reportObject = new Report({copied-raw-report-object-from-debug});
reportObject.setDateRanges(["LAST_90_DAYS"]); // Optionally change the date-range.
const reportData = await ReportData.get(reportObject);
return {reportData};

This is less clean than building up the report object using the API, but is much faster in development.

Report errors

A report error can be checked and handled in a few different ways.

The first option is to let the <Chart> or <Table> report visualization components handle any errors.
This is the easiest option in case you don't want the whole Insight to fail, but if it's ok if only this specific report doesn't display:

JS code:
const reportObject = new Report({sql: "SELECT nothing"});
const reportData = await ReportData.get(reportObject);
return {reportData};
JSX code:
<Chart data={data.reportData} />

All other options below make the complete Insight fail. This is best if any code that runs after the report, is dependent on the report results.

Because a failed ReportData.get returns an error object, we can return that directly. As explained in the adding code page, an error object can be returned directly, so that it gets picked up and the error is shown to the end-user.

To check if the report has an error we first need to use Utils.validResult(reportData):

const reportObject = new Report({sql: "SELECT nothing"});
const reportData = await ReportData.get(reportObject);
if (!Utils.validResult(reportData)) {
return reportData;
}

Alternatively we can return a string directly, which is displayed as error to the end-user:

const reportObject = new Report({sql: "SELECT nothing"});
const reportData = await ReportData.get(reportObject);
if (!Utils.validResult(reportData)) {
return "This report has an error";
}

Or we can return an error object with more details:

const reportObject = new Report({sql: "SELECT nothing"});
const reportData = await ReportData.get(reportObject);
if (!Utils.validResult(reportData)) {
return {
"code": "error",
"title": "This report has a problem",
"explanation": "Nothing doesn't exist!",
"backtrace": "Query failed: line 1:8: Column 'nothing' cannot be resolved"
};
}

Similarly an error can happen in other ways as well:

const reportObject = new Report({
reportType: "user-graph",
timeUnit: "day",
dateRanges: ["LAST_30_DAYS"]
}).addUserCount();
reportObject.addGroupBy({table: "users", property: "u_col_doesnt_exist"});
const reportData = await ReportData.get(reportObject);
if (!Utils.validResult(reportData)) {
return reportData;
}
return {reportData};

Using questions/variables

As described in the Questions & Variables page, the questions object contains end-user assignments for things such as choosing an conversion event, user/event property or any simple property such as a date or number.

Questions can be used with the report object in a few ways. Below are a few examples:

Event variables

End-user answers what three events to use to make a funnel report. Because events of the Report object is just an array event names, we can assign them as follows:

const reportObject = new Report({
reportType: "funnel",
timeUnit: "total",
dateRanges: ["LAST_180_DAYS"],
events: [questions.event_a.event, questions.event_b.event, questions.event_c.event]
});

User/event property variables

End-user picks a user property, such as campaign source, to group a report on:

const reportObject = new Report({
reportType: "user-graph",
timeUnit: "day",
dateRanges: ["LAST_30_DAYS"]
}).addUserCount();
reportObject.addGroupBy(questions.user_campaign_property);

Similarly event property variables can be used:

reportObject.addGroupBy(questions.event_price_property);

User/event item object

A helper method under user/event property variables, questions.event_price_property.item(), returns an item object which can be used directly when constructing manual report items, such as a calculation:

const calculateCLV = {
"calculate": [
Object.assign({}, {
"aggregate_function": "avg",
"eventFilter": {
"conjunctions": [],
"countEventProperty": "sum",
"queries": []
},
"filter": {
"conjunctions": [],
"queries": []
}
}, questions.event_price_property.item())
],
"color": "purple",
"name": "CLV per user",
"operators": []
};
// Add CLV calculation
report.addItem(calculateCLV);

User property variables can be used in a similar way.

For more details and recipes see the API-Library on the Report.