Increment and decrement counters

The Counters API allows a counter to be incremented and decremented in Qubit's Data Store. Counters are stored in 24 hour buckets, so at midnight GMT, a new bucket is created and the counter is reset to 0.

A related API, also used to customize Social proof, is the Timestamp API.

Unique values

Before using the Counters API, you will require the following unique values:

Name

Description

<tracking_id>

Qubit tracking Id for the property the request is made from. This will be provided by your Customer Success manager at Qubit

<visitor_id>

Unique site visitor Id, generated by the smartserve script on the page and set in qb_permanent and _qubitTracker

Incrementing a counter

Incrementing a counter is done via making a POST request to the endpoint. The POST body must be as defined below. The counter will be incremented by 1, or created if it does not exist yet:

POST stash.qubitproducts.com/stash/v1.1/count/incr/<tracking_id>/public/<visitor_id>:<counter_name>
{ dimension: 'date' }

<counter_name> must be a URL friendly string, and used to identify the counter.

If the counter is incremented (or created) successfully, the response will be a JSON object with the status set to 200, and the data key being the full name of the counter:

{
  status: 200,
  data: '<tracking_id>:<counter_name>:YYYY-MM-DD'
}

Decrementing a counter

Decrementing a counter is done via making a POST request to the endpoint. In this release, the POST body must be as defined below. The counter will be decremented by 1:

POST stash.qubitproducts.com/stash/v1.1/count/decr/<tracking_id>/public/<visitor_id>:<counter_name>
{ dimension: 'date' }

<counter_name> must be a URL friendly string, and used to identify the counter.

If the counter is incremented (or created) successfully, the response will be a JSON object with the status set to 200, and the data key being the full name of the counter:

{
  status: 200,
  data: '<tracking_id>:<counter_name>:YYYY-MM-DD'
}

Retrieving a counter

Retrieving a counter is done via making a GET request to the endpoint:

GET stash.qubitproducts.com/stash/v1.1/count/get/<tracking_id>/public/<visitor_id>:<counter_name>:<date>

<date> should be the date from which you want to get the counter for in the format YYYY-MM-DD (the full key is returned in an increment or decrement response under the data key).

If the counter exists, then the response will be as below:

{
  status: 200,
  data: '<count>'
}

Where:

  • <count> is the value of the counter

Retrieving multiple counters

It is possible to retrieve multiple counters at once using the batch endpoint. This requires sending an array of counters to fetch:

POST stash.qubitproducts.com/stash/v1.1/count/getbatch/<tracking_id>/public
{
  keys: [
    '<visitor_id>:<counter_name>:<date>',
    '<visitor_id>:<counter_name>:<date>',
    '<visitor_id>:<counter_name>:<date>'
  ]
}

INFO: The batch size limit is 10 keys.

For the counters that exist, then the response will be as below:

{
  status: 200,
  data: {
    <visitor_id>:<counter_name>:'<count>',
    <visitor_id>:<counter_name>:'<count>',
    <visitor_id>:<counter_name>:'<count>'
    // ...
  }
}

Counts with configurable time buckets

To implement use cases that require time buckets that are not exactly 24 hours (for instance, counts that need to expire after 15 minutes), use the following requests.

Incrementing counts

Request template:

POST tally-1.qubitproducts.com/tally/<tracking_id>/<op_type>/<counter>/<countable>/<window_size>

An HTTP POST request is sent to increment a specific counter. The following parameters are required:

  • tracking_id - tracking Id
  • op_type - for counts requiring configurable time, this will be fixed as “ecount”
  • counter - type of interaction to count e.g. views from a specific country
  • countable - items to be counted, e.g. product Id or a specific airline route
  • window_size - the time window (in minutes) over which the most popular results have to be aggregated. Range is between 1 minute and 30 days

DANGER: The parameters opType, trackingId, counter, period cannot contain forward or back slashes / . Use underscores instead.

Example request:

POST tally-1.qubitproducts.com/tally/<tracking_id>/ecount/views/<countable>/60

The response to a successful POST call will be:

{ status: 'saved' }

In case the request failed, the response will be:

{ error: 'not saved' }

Retrieving counts

Request template:

GET tally-1.qubitproducts.com/tally/<tracking_id>/<op_type>/<counter>/<countable>

An HTTP GET request is sent to retrieve the value of a specific counter. Following parameters are required:

  • tracking_id - tracking Id
  • op_type - for counts requiring configurable time, this will be fixed as “ecount”
  • counter - type of interaction to count e.g. views from a specific country
  • countable - items to be counted, e.g. product Id or a specific airline route
  • window_size - the time window (in minutes) over which the most popular results have to be aggregated. Range is between 1 minute and 30 days.

DANGER: The parameters opType, trackingId, counter, period cannot contain forward or back slashes / . Use underscores instead.

INFO: It takes at least a minute for data results to appear after a corresponding POST request is made.

Example request:

GET tally-1.qubitproducts.com/tally/<tracking_id>/ecount/views/<countable>

If the count is available, the response will be a key/value pair, where key is data and value is the actual count that has been received for this key.

Example response:

{ data: '<count>'}

Top-K counts

To implement use cases that require 'top K' counts, for example, to implement a product feed of the most popular products by visits, searches or purchases, use the following requests.

Incrementing counts

Request template:

POST tally-1.qubitproducts.com/tally/<tracking_id>/<op_type>/<counter>/<countable>/<window_size>

An HTTP POST request is sent to increment a specific counter. The service will take as input the following parameters:

  • tracking_id - tracking Id
  • op_type - for the top K counts use case, this will be fixed as “topk”
  • counter - type of interaction to count e.g. views from a specific country
  • countable - items to be counted, e.g., product Id
  • window_size - the time window (in minutes) over which the most popular results have to be aggregated. Range is between 1 minute and 30 days

DANGER: The parameters opType, trackingId, counter, period cannot contain forward or back slashes / . Use underscores instead.

Example request:

POST tally-1.qubitproducts.com/tally/<tracking_id>/<op_type>/views:uk/abc1234/60

The response to a successful POST call will be:

{ status: 'saved' }

In case the request failed, the response will be:

{ error: 'not saved' }

Retrieving counts

Request template:

GET tally-1.qubitproducts.com/tally/<tracking_id>/topk/<counter>/<k_value>

The list of top-K products can be retrieved by sending an HTTP GET request. The parameters to be included in this are as follows:

  • tracking_id - tracking Id
  • op_type - this will be fixed for top-K operations, i.e. “topk”
  • counter - type of interaction to count e.g. views from a specific country
  • k_value - query string which specifies the number of most popular results to retrieve, e.g., k_value = 10 for top 10, and so on.

INFO: If k_value is not specified, a default of 25 is returned.

INFO: It takes at least a minute for top K results to appear after a corresponding POST request is made.

Example request:

GET tally-1.qubitproducts.com/tally/<tracking_id>/topk/views:uk/?k=10

The response will be a sorted JSON array of key/value pairs, where key is the uniquely identifiable string composed according to the format:

'<namespace>::<counter>::topk::<countable>'

and value is the actual count that has been received for this key. The array will be sorted in descending order of values, so the most frequent item will occupy the first index.

Example response:

{
  data: [
    [ 'qubit::counter1::topk::countable2', '3.0' ],
    [ 'qubit::counter1::topk::countable3', '2.0' ],
    [ 'qubit::counter1::topk::countable1', '1.0' ]
  ]
}

Optional metadata

In addition to saving counts, you can save additional data such as product names and image URLs. This metadata must be sent in the body of the request.

The body needs to consist of a single JSON object with a single key “metadata”, the value of which must be a string. An example is shown below:

{
  metadata: '{\'id\':1,\'first_name\':\'Debra\',\'last_name\':\'Bell\',\'email\':\'dbell0@bbb.org\',\'gender\':\'Female\'}'
}

The following rules apply to using metadata:

  • Not all countables associated with a counter need to have metadata
  • Successive POSTs, with a correct body for a countable, update its metadata
  • Metadata is not removed if a successive POST does not contain metadata
  • Metadata for a countable is updated instantly whilst updates to its count are a function of its window_size
  • The maximum metadata size allowed is 16384 characters. Note that this is a per countable limit

Response codes

Each response message contains a response code, which indicates the status of the original query. The format of the response will be JSON such as the below:

{ status: 200 }

This response code can be checked to quickly determine whether a query was successful or a retry needs to be made. Note that this is not related to the actual HTTP response code, which will always be 200.

Code

Description

200

The operation completed successfully

400

The operation did not complete due to a client side error. This code will be returned when the request parameters had invalid values

404

The operation did not complete due to a client side error. This will be returned when the requested key or keys are not found

500

The operation could not be completed due to a server side error. A retry needs to be made in this case

Last updated: March 2022
Did you find this article useful?