Serving & Reading Datasets
Once a version is live, reads are answered at the edge: a single key lookup, cached close to your visitors for roughly 60 seconds. There are two read clients (the browser snippet and the Node SDK) and both follow the same failure policy: they never throw and never block the page. Any problem (unknown slug, no live version, network failure) resolves to a found: false result, so a dataset hiccup can degrade a feature but never break your site.
Browser snippet: avsb.dataset(slug)
avsb.dataset(slug) returns a handle with two async methods:
var ds = avsb.dataset('pdp-related');ds.get('SHIRT123').then(function (result) { // result.found, result.items / result.row / result.member, result.meta});ds.has('CUST-10381').then(function (isMember) { // true or false});get(key) result shape
get resolves to an object whose data field depends on the dataset type:
| Field | Type | Present for | Meaning |
|---|---|---|---|
found | boolean | All types | Whether the key resolved to live data |
items | array | FEED | The row's ordered items array |
row | object | TABLE | The full row object |
member | boolean | LIST | Whether the key is in the list |
meta | object | All types | meta.slug and meta.version, which dataset version answered |
has(key) resolves to a plain boolean and works on any type; for a LIST it is the idiomatic membership check.
An unknown slug, a dataset with no live version, or any fetch failure resolves to a result with found: false: check found before using the data and you are safe in every case.
Example: target-list gating in variation code
Gate a variation's change on membership in a LIST dataset:
// initVariation: show the beta banner only to customers in the target listvar visitorCustomerId = document.body.getAttribute('data-customer-id') || '';avsb.dataset('beta-customers').has(visitorCustomerId).then(function (isMember) { if (!isMember) return; var banner = document.querySelector('#beta-banner'); if (banner instanceof HTMLElement) banner.style.display = 'block';});Example: content by product (TABLE)
Look up per-product copy on a product detail page:
var skuEl = document.querySelector('[data-sku]');var sku = skuEl && skuEl.getAttribute('data-sku');if (sku) { avsb.dataset('pdp-copy').get(sku).then(function (result) { if (!result.found) return; // fall back to the page's default copy // A TABLE row is the columns you uploaded, so name them here var copy = /** @type {{ headline?: string }} */ (result.row); var headline = document.querySelector('.pdp-headline'); if (headline && copy.headline) { headline.textContent = copy.headline; } });}Example: rendering a feed row (FEED)
Render a recommendations ribbon from a feed: each item carries everything the UI needs, so this is one read and zero follow-up requests:
var currentProductId = document.body.getAttribute('data-product-id') || '';avsb.dataset('pdp-related').get(currentProductId).then(function (result) { if (!result.found || !result.items?.length) return; const ribbon = document.querySelector('#related-ribbon'); if (!ribbon) return; result.items.forEach(function (row) { // A FEED item is the object you uploaded, so name its fields here var item = /** @type {{ href: string, image: string, title: string }} */ (row); var card = document.createElement('a'); card.href = item.href; card.innerHTML = '<img src="' + item.image + '" alt="' + item.title + '">' + '<span>' + item.title + '</span>'; ribbon.appendChild(card); });});Lookups are cached at the edge with a 60-second lifetime, and the pointer to the live version refreshes on the same cadence. After you activate a new version, all readers converge on it within about a minute: fully-old, then fully-new, never a mix.
Node SDK: client.datasets.get(slug, key)
The Node SDK (@avsbhq/node v1.3.0 or later) reads the same live data from your server:
import { AvsbServer } from '@avsbhq/node';const client = new AvsbServer({ sdkKey: process.env.AVSB_SDK_KEY ?? '' });await client.onReady();const result = await client.datasets.get('pdp-copy', 'SHIRT123');if (result.found) { // TABLE / FEED: result.value is the parsed row object. // LIST: result.value is true (membership hit). console.log(result.value, result.meta.slug, result.meta.version);}The result shape is slightly flatter than the snippet's:
| Field | Type | Meaning |
|---|---|---|
found | boolean | Whether the key resolved to live data |
value | object | true | The row object for TABLE/FEED; true for a LIST membership hit |
meta | object | meta.slug and meta.version |
Like the snippet, the Node SDK degrades instead of throwing: an empty slug or key, an SDK that is not yet ready, an unknown dataset, a dataset with no live version, or a network failure all return { found: false }. Treat found: false as "use your fallback", not as an error to handle.
Both clients are built so the absence of data is a normal outcome, not an exception. Always ship a sensible default (the page's existing copy, an empty ribbon, the non-beta experience) and let dataset data enhance it when present.