Install a zone
A page shows a zone with the Web SDK and the zone's key. The zone page's Install tab gives you both.
The snippet
The Install tab shows this snippet for its zone, with your API URL filled in:
<script type="module" src="https://api.example.com/sdk/v1/taleart.js"></script>
<!-- Optional, once per page: <script>Taleart.init({ locale: "en" })</script> -->
<taleart-view zone-key="YOUR_ZONE_KEY"></taleart-view> Replace YOUR_ZONE_KEY with the zone's key. Right after an admin issues the key, the Install tab shows the snippet with the key already in it, ready to copy; after that the key is never shown again. The second line is optional: Taleart.init sets page-wide options once, such as the locale, the strings and the theme.
| Attribute (property) | Meaning |
|---|---|
zone-key (zoneKey) | Required. The zone's key, tak_…. It names the zone, so the element needs no slug. |
api-url (apiUrl) | Optional. The TaleArt API origin; by default the origin the script was loaded from. |
locale (locale) | Optional. The language of the viewer's own texts for this element; by default the page's. |
strings (property only) | Optional. Replacement texts for this element, an object set from script. |
theme (theme) | Optional. Theme fields for this element only (JSON in the attribute). |
Page-wide options
The script loads once per page. Taleart.init({ apiUrl, locale, strings, theme, hooks }) sets options for every element on the page, before or after the elements connect; each option is optional, and an attribute on one element overrides it.
With npm
If your app bundles the Web SDK itself, install the package and import init from it. The element markup is the same.
npm i @lempert/taleart
import { init } from '@lempert/taleart';
// Optional, once per page: init({ locale: "en" })
<taleart-view zone-key="YOUR_ZONE_KEY"></taleart-view>The zone key
- A zone has at most one active key. An admin issues it on the zone's Install tab; it is shown once, so copy it then.
- It sits in your page's HTML, so anyone who sees it can read that one zone, while the zone has a display and visible content. It cannot read any other zone, so treat what the zone shows as public.
- Put the key only in the
zone-keyattribute (or thezoneKeyproperty), never in a query string: a URL ends up in server logs and Referer headers. The SDK sends it only in theAuthorizationheader. - Rotating it issues a new key and stops the old one at once, for that zone only: update the pages that use it. Revoking it stops that zone until a new key is issued. Other zones are not affected.
- The project's site key (
tas_…) is for server-side or legacy Delivery API calls, which also name the zone with?zone=. A web page does not use it.
Several zones on one page
Load the script once and add one element per zone, each with its own zone key.
<script type="module" src="https://api.example.com/sdk/v1/taleart.js"></script>
<taleart-view zone-key="YOUR_ZONE_KEY_HOME_TOP"></taleart-view>
<taleart-view zone-key="YOUR_ZONE_KEY_HOME_PROMO"></taleart-view>Where the SDK comes from
The TaleArt API serves the Web SDK at https://api.example.com/sdk/v1/taleart.js, an ES module. A deploy replaces it at the same URL, and browsers keep it for five minutes. Its v1 follows the Delivery API's version.
Pinning it with Subresource Integrity
The same build is also served at a URL pinned to its content, /sdk/v1/taleart.<hash>.js, cached for a year. The zone page's Install tab shows the URL and its integrity value under Pin this SDK version, each with a Copy button, and Copy pinned script tag copies the whole tag. (<api>/api/v1/install, opened where you are signed in to the dashboard, gives them as sdkPinnedUrl and sdkIntegrity, with sdkBuildsKept.)
<script type="module" src="https://api.example.com/sdk/v1/taleart.<hash>.js" integrity="sha384-…" crossorigin="anonymous"></script>The browser then refuses any other file. By default the API keeps the last 5 SDK builds this server served at their pinned URLs, the current one included, so a pinned page keeps working through the next 4 SDK builds the server serves: update the pin before then. The Install tab says the server's own number; when it keeps only the current build, a pinned URL stops working at the next SDK build. An older or unknown hash answers 404, which no cache keeps.
For the people who run TaleArt: the API writes each build it serves, at start and once the bundle has not changed for a second, to the folder SDK_BUILDS_DIR names (unset or empty: .data/sdk-builds, outside the build output), and keeps the newest SDK_BUILDS_KEPT (5 by default, at least 2: during a rolling deploy an old and a new process each keep their build). The folder must persist across deploys (a volume, in a container) and be shared by every API process that serves the same URLs, on hosts with synchronised clocks; in production the API warns at start when it holds no build. SDK_BUILDS_DIR=off (or false, none, no, 0) keeps only the current build. Deploy a new SDK file atomically: write it elsewhere on the same disk, then rename it into place.
The test page
Open test page on the Install tab shows the zone on a page TaleArt serves, before you touch your site:
https://api.example.com/sdk/v1/test-page#zoneKey=YOUR_ZONE_KEY- The zone key travels only in the URL fragment (after
#), which a browser never sends to a server; the page removes it from the address bar. Opened ashttps://api.example.com/sdk/v1/test-page, it asks you to paste the key. - The page stores the key nowhere and gives it only to the Web SDK.
Theme for one zone
The project's theme styles every zone. A page can override it for one zone, by the zone's slug, or for one element with its theme attribute. Import configureZone from exactly the URL of your script tag (the pinned one, if you pin it): another URL loads a second copy of the SDK, and the elements never see its settings.
<script type="module" src="https://api.example.com/sdk/v1/taleart.js"></script>
<script type="module">
import { configureZone } from 'https://api.example.com/sdk/v1/taleart.js';
// Every <taleart-view> that shows the zone with slug "home-top"; other zones keep the project's theme.
configureZone('home-top', { theme: { ringStyle: 'solid', ringColors: ['#0055ff'] } });
</script>The visitor id
Each device gets a visitor id: a random UUID v4 the SDK makes once and keeps on the device, in the page's local storage on the web (taleart.visitor) and in the SDK's own store in an app. It is random, not derived from the person or the device, and tied to no account. It is still a stable identifier of a browser or an app install, so cover it in your privacy notice and your consent setup like other local storage.
The SDK sends it only to the Delivery API, in the X-TaleArt-Visitor header, so the API can limit requests per visitor and many visitors behind one network each get their own allowance. It also keys a visitor's vote on a poll, answer to a quiz and rating on a Rating, which count once per visitor; each needs the id. On the web the SDK keeps the visitor's answers in local storage too (taleart.responses), to show them on a return visit. Because the id is made on the device, poll and quiz counts and Rating averages are indicative, not tamper-proof: clearing site data, a private window or a script that invents ids can answer again, within the rate limits. Do not use a poll, a quiz or a Rating where the result must be trusted. A quiz's correct answer is published with the tale, so a quiz is not a secure test. Proxies, CDNs and access logs in front of the API can see the header too.
- On the web, clearing the site's data makes a new id, and Safari may clear script-written storage after seven days without a visit. Where local storage is blocked, the id lasts one page load.
- In an app, clearing the app's data makes a new id. A reinstall does too, unless a device backup restores it: Android Auto Backup and iOS backups restore the SDK's store. To start fresh after a reinstall on Android, exclude
sharedpref/taleart-sdk.xmlin the app's backup rules (android:fullBackupContentandandroid:dataExtractionRules).
When nothing shows
- A missing, revoked or rotated zone key, renders nothing and logs one console error per element.
- The Delivery API limits how often one visitor may ask (by default bursts of 600, then 20 requests a second), and one address ten times that in all. Over the limit it answers 429, and the element renders nothing and logs one console error; a reload later shows the zone again. A flood from one device behind a shared network (an office or a mobile carrier) can use up that address's allowance for everyone behind it.
- If you run the API behind a proxy, set
TRUST_PROXYto exactly the proxies in front of it. Otherwise every visitor is counted as the proxy's address, and they all share one allowance. - Otherwise, open the zone page: it says Not visible: and why, such as "zone has no display", "group is off" or "zone not installed".