Overview
A custom fetcher is an optional processing layer applied on top of a datasource’s standard retrieval. Instead of returning the stored rows as-is, the datasource runs the data through additional logic every time it is queried — filtering it to a single user, reshaping columns into rows, excluding products, or computing an aggregation. Custom fetchers run at query time, so they always reflect the latest stored data and the runtime context (such as the user being personalised for). This page documents the generic custom fetchers — the ones available to any account. Some custom fetchers implement customer-specific logic and are not covered here.Custom fetchers do not have a self-serve interface yet. They are configured on a Datasource by Reelevant. Contact your Technical Account Manager if you want to enable one.
Retrieval modes
A datasource retrieves data in one of three modes, and each custom fetcher is built for one or more of them:
The summary table below shows which mode each generic custom fetcher applies to.
Setting up a custom fetcher
There is no self-serve interface for custom fetchers yet, so they are configured through the Datasources API on the datasource’s draft version. Setup is two steps: declare the fetcher with theconfigure_fetcher step, then promote the version with the validate step.
Both calls require an access token — see Authentication for how to obtain one.
payload.name is the fetcher identifier (e.g. per-user, generic-unwind-rows, product-exclusion), and payload.params holds the configuration fields documented for each fetcher below. For fetchers that take no configuration, send an empty object: "params": {}.
The
validate step promotes the draft version to live. For pull-and-store datasources it also enqueues a verification job, so the new version only goes live once that job succeeds.Per User
Restricts the datasource so a query returns only the records that belong to the user currently being personalised. It works on any retrieval mode and automatically targets the user identifier field defined in the Field Mapping (the CRM user field, or the purchase user field for a purchases datasource). When a datasource has a timestamp field, results are automatically sorted from most recent to oldest. The fetcher also exposes the resolved locale field so a Workflow can read the user’s locale alongside the data. This custom fetcher takes no configuration.Use this on shared datasources (such as a CRM, purchases, or analytics feed) where a Workflow must only ever see the active user’s own rows.
Unwind Rows
Reshapes each stored row by turning its columns into several rows. One column is kept as an identifier, and every other column becomes its own row, with the original column name stored in one field and the cell value in another.Configuration
Before and after
Consider a stored row that lists three category affinities for a user:
With source =
user, destination = user, and columnDestination = category, the fetcher unwinds it into:
Sorting by the value field is applied after unwinding, so you can rank the produced rows by their numeric value when valueType is
number.Product Exclusion
Filters a product datasource against a second datasource that lists items to keep or remove. A typical use is hiding products a user has already purchased, or restricting recommendations to an allow-list.Configuration
How it works
- The fetcher reads the matching IDs from the exclusion datasource, respecting any query filters that apply to both datasources.
- In
exclusionmode, those IDs are removed from the product results; ininclusionmode, only those IDs are kept. - In
inclusionmode, if the exclusion datasource returns no IDs, the product query returns no rows.
The exclusion list is read up to a configured limit. For very large lists, talk to your Technical Account Manager about the applicable threshold.
Expired Product Lifetime
Surfaces products that a user is due to repurchase, based on their purchase history and an expected product lifetime. It joins the current product datasource with a purchases datasource, computes when each previously bought product should run out, and returns only the products whose next purchase date falls inside a configured window.Configuration
Each entry in temporalities describes one repurchase window:
How it works
The fetcher looks at each product the user previously bought and predicts when they will need it again. The way the lifetime is derived depends on how many times the user bought that product.- It reads the user’s purchases (most recent first) and groups the purchase dates per product reference.
- For each product it derives an expected lifetime and an expected next purchase date (see the two behaviours below).
- It keeps the product only if today falls inside the matching temporality window — from
windowStartdays before the next purchase date towindowEnddays after it. - Kept products are enriched with
purchaseCount,lastPurchaseDate, andnextPurchaseDate, and can be sorted by any of these.
Behaviour 1 — single purchase (lifetime lookup)
When the product was bought once, the fetcher cannot measure a real repurchase interval, so it reads the expected lifetime from the product’s own lifetime field in the Field Mapping. The next purchase date islastPurchaseDate + lifetime.
Example — a coffee capsule pack with a lifetime field of 30 days, bought once on 1 March, using the default window (windowStart 0, windowEnd 90):
The capsule pack is returned for any user query run between 31 March and 29 June. If the product has no lifetime field, a single-purchase product cannot be evaluated and is skipped.
Behaviour 2 — multiple purchases (computed average)
When the product was bought several times, the fetcher ignores the static lifetime field and instead computes the average interval between consecutive purchases for this specific user. The next purchase date islastPurchaseDate + averageInterval.
Example — the same capsule pack bought on 1 January, 1 February, and 1 March, using the default window:
Using the user’s own cadence makes the prediction far more accurate than a single static lifetime. If the computed average is less than one day, the product is skipped.
When no temporalities are configured, a default rule is applied: products with a lifetime up to 365 days that are due within the next 90 days (
maxLifetime 365, windowStart 0, windowEnd 90).Proxy Lock
Applies only to real-time proxy datasources. When Reelevant receives many concurrent requests that would trigger the same upstream call, this fetcher lets the first call run and makes the others wait briefly, so the result can be served from cache instead of repeating the call.Configuration
Use this to protect a rate-limited or expensive upstream API when a single delivery fans out into many identical real-time calls.
Proxy Aggregation
Applies only to real-time proxy datasources. After fetching the live response, it computes a single aggregation over a chosen field and adds the result to every returned row.Configuration
Non-numeric and missing values are ignored. If no numeric values are found, the output field is empty.
Related pages
- Datasource Reference — building derived datasources from existing ones.
- Special Configurations — other computed datasource types (Best Products, Merge, Cross-sell).
- Field Mapping — defining the fields a custom fetcher reads and writes.