Skip to main content

Analytics

InCountry provides two reporting use cases. Reporting of detailed regulated data within a country, and reporting of aggregated and anonymized data outside a country.

  • Aggregate reporting outside a country uses InCountry’s aggregation functions so that reports running outside a country can provide aggregates of regulated data. For example, a Sales Manager can see the total pipeline amount by city, but can not drill down and see each prospect.

  • Detailed reporting within a country can combine regulated data and unregulated data, with filtering, grouping, and aggregation. Your application can continue to provide drill down functionality and users can use data they are authorized to see. For example, a Sales Manager can see the total pipeline amount by city and drill down and see each prospect.

Aggregated Reporting

To implement the aggregated reporting within your web application, you can utilize the REST API that provides the aggregation endpoint:

POST /api/models/{schemaName}/aggregate.

Please see the example of the aggregation request structure.

Example

{
"metrics": {
"total_spending": { // arbitrary name for the metric
"func": "sum", // aggregation function to apply, it will summarize values against the specified yearly_spending field
"key": "yearly_spending" // or other Integer/Decimal key from the schema
},
"users_count": {
"func": "count" // aggregation function to apply, it will count records in the group
}
},
"filter": { // filter to apply.
"yearly_spending": { "$gte": 5000 } // search for the records with yearly_spending >= 5000
},
"group_by": {
"limit": 100,
"keys": [
"first_name"
]
}
}

After the initial request, the cursor is returned to allow you to iterate over all the results. For subsequent requests, when the cursor is available, use the following request body format:

{
"next": "<cursor_val>"
}

Within the metrics section, you can define the aggregation parameters:

ArgumentDescription
metricNameNYou can declare the aggregated metric, for example, total_sales_amount, record_count, or total_revenue.
funcYou can define the aggregation function to apply: count - count records; does not accept additional params. sum - takes a Integer/Decimal field as a param; summarizes values against the specified field.
cURL request

curl --request POST \
--url 'https://{restApiURLAddress}/api/users/aggregate' \
--header 'Authorization: Bearer {ACCESS_TOKEN}' \
--header 'Content-Type: application/json' \
--data '{
"metrics": {
"total_spending": { // arbitrary name for the metric
"func": "sum",
"key": "yearly_spending" // or other Integer/Decimal key from the schema
},
"users_count": {
"func": "count"
}
},
"filter": { // filter to apply.
"yearly_spending": { "$gte": 5000 } // search for the records with yearly_spending >= 5000
},
"group_by": {
"limit": 100,
"keys": [
"first_name"
]
}
}'

// For the subsequent requests, when `cursor` is available:

curl --request POST \
--url 'https://{restApiURLAddress}/api/users/aggregate' \
--header 'Authorization: Bearer {ACCESS_TOKEN}' \
--header 'Content-Type: application/json' \
--data '{
"cursor": <cursor value>
}'

In the happy path, this request will return HTTP code 200 along with the following data:

Example

    {
"meta": {
"next": "fgfUewn=="
},
"data": [
{
"group": {
"keys": {
"first_name": "John"
}
},
"metrics": {
"total_spending": 10000,
"users_count": 1
}
},
{
"group": {
"keys": {
"first_name": "Jake"
}
},
"metrics": {
"total_spending": 12000,
"users_count": 2
}
}
]
}

In the example, the aggregated reporting request returned two groups: one with the name John and the second with the name Jake. In each of these groups, the count function was used to calculate the number of participants, and the sum function was used to calculate the sum of the participants' salaries.

For more details on how to properly implement aggregated reporting, please see Search in REST API.

Detailed Reporting

To implement the detailed reporting within your web application, you can use the Web Services which will process analytics Web Services already existing in your application. For example, unredacting the GET responses querying records with regulated data.

The Web Services solution enables users to search data by regulated fields stored in the InCountry Vault, as well as by non-regulated fields stored in the application database. It's important to note that Web Services initially searches for appropriate records in the InCountry Vault using regulated fields. It then sends the list of found records' identifiers combined with the search query by non-regulated fields to the application backend. The application backend is responsible for returning a filtered list of entities. In this scenario, the response from the application backend will contain redacted values (hashes/tokens), which are later unredacted by Web Services using the regular unredaction mechanism.

For implementing this solution, your application backend should be a RESTful API that returns and accepts data in JSON format. The following endpoints should be implemented:

  • The main search, which must operate with entities/resources and return a list of entities/resources with some kind of ID as a response to a search query. Below is an example of such an endpoint:

        // Request
    // POST https://backend.com/api/users/search
    // Authorization: <TOKEN>
    // Request body example:
    {
    "ids": ["id1", "id2", "id3"],
    "car": "Ford"
    }
  • The search authentication check endpoint including token-based authentication (OAuth, JWT). Below is an example of such an endpoint:

     // Request
    // POST https://backend.com/api/search-auth
    // Authorization: TOKEN

Based on these endpoints, once can configure a search rule using InCountry Portal:

and unredaction rule for the main search endpoint:

For the details on how to properly implement this, please see Search in Web Services Proxy.