Elements

Terudo Elements reference. The five drop-in elements (destination-picker, plans, trip-offer, booking-banner, esim-status), loading, options, callbacks, styling, sessions, checkout, test mode, CSP.

Elements are pieces of Terudo's eSIM shop that render inside your own page: no iframe, your font, your colours. The traveller chooses a plan in your page and pays on Terudo's hosted checkout, where Terudo is the seller (commission model). One script, one publishable key.

Load the script

<script src="https://terudo.com/elements/v1.js" data-key="pk_live_…" data-locale="fr" defer></script>

Script attributes:

Attribute Meaning
data-key Your publishable key (pk_live_…, pk_test_…, or the demo key pk_test_terudo_demo_public). With it, the script creates window.terudo and mounts every element marked data-terudo once the page is ready.
data-locale fr, en, de, es, it, pt, zh, ar or hi. Default: the page's <html lang>, then fr.
data-session A client_token from an element session (see Sessions).

Never put a secret key (sk_…) in a page.

Two ways to mount

Declarative: any element with data-terudo="<name>" and its options as data-* attributes (camelCase options become kebab-case: returnUrl → data-return-url, esimId → data-esim-id, plansInto → data-plans-into).

<div data-terudo="trip-offer" data-destination="JP" data-start="2027-04-02" data-end="2027-04-16" data-profile="heavy"></div>

Elements added to the page later (single-page apps) are mounted by calling terudo.autoMount() (or terudo.autoMount(containerElement)). An element is mounted once; it carries data-terudo-mounted afterwards.

JavaScript: create an instance and mount where you want. Callbacks are only available this way.

const terudo = Terudo({
  key: 'pk_live_…',
  locale: 'en',
  session: clientToken,                       // optional, from POST /element_sessions
  appearance: { color: '#0a5b8a', onColor: '#ffffff', radius: '10px', font: 'inherit' },
});

const offer = terudo.mount('trip-offer', '#esim-offer', {
  destination: 'MA', start: '2026-12-03', end: '2026-12-09', profile: 'normal',
  email: '[email protected]', returnUrl: 'https://www.your-agency.example/bookings/48213',
  onCheckout(order) { analytics.track('esim_checkout', { order: order.order_id }); },
  onError(error) { console.warn(error.code, error.message); },
});

offer.update({ start: '2026-12-04' });        // re-renders with new options

Terudo(config) returns { mount(name, target, options), autoMount(scope?), api(path, options), locale, key, origin, elements }. target is a CSS selector or a DOM element; mount empties it first. mount returns { host, update(options) }.

The elements

destination-picker

The destinations of the catalogue, each with its "from" price.

Option Type
title string Heading. Default "Choose your destination".
onSelect(code, plan) function Called when a destination is picked, with its code and cheapest plan.
plansInto selector or element Mounts plans for the picked destination there.

plans

Every plan of one destination, cheapest first, each with its price and a button that asks the traveller's email and opens the checkout.

Option Type
destination string, required ISO code (MA) or region (EU-35).
days integer 1–30 Adds daily plans of that length.
email, returnUrl, onSelect(plan), onCheckout(order), onError(error) See Checkout and Callbacks.

trip-offer

Destination and dates in, the recommended plan out (the cheapest that covers the stay plus one buffer day), the other plans a click away. The piece for a visa approval, an itinerary or a trip page.

Option Type
destination string, required
start, end YYYY-MM-DD, required Arrival and departure. 60 days at most.
profile light | normal | heavy Estimated use: 0.5, 1 or 2 GB a day. Default normal.
title string Replaces "Your trip: dates".
email, returnUrl, onSelect, onCheckout, onError

booking-banner

One line for a booking confirmation: the recommended plan and its price, with a button that opens into the full trip-offer in place.

Option Type
destination, start, end, profile As trip-offer.
title, subtitle, cta string Override the banner's texts and the button label.
onOpen(quote) function Called when the traveller opens the offer.
email, returnUrl, onCheckout, onError

esim-status

The traveller's eSIM inside your own customer area: state, data used, install buttons while not installed, validity, link to Terudo's full eSIM page.

Option Type
esimId string, required The esim.id of the order (API) or the token in the traveller's eSIM page link.
pageUrl false Hides the link to the full page.
onLoad(esim) function Called with the eSIM data (no activation code: that stays server-side).

States shown: preparing, not_installed, active, used_up, ended, suspended, deleted, refunded.

Checkout

The traveller never pays in your page. After choosing a plan they give their email (unless you passed email), the element creates a commission order (POST /public/checkout) and sends the browser to checkout_url on terudo.com. There the traveller accepts Terudo's terms and pays in their currency; the eSIM arrives by email right after payment. Then they are sent to returnUrl:

  • kept when its origin is one of the sites listed on your publishable key, or when it comes from an element session;
  • otherwise ignored, and the traveller stays on Terudo's confirmation page.

onCheckout(order) runs just before the redirect, with { object: "checkout", order_id, checkout_url, status }. Return false to stop the redirect and handle order.checkout_url yourself (open it in a new tab, a webview, …).

Checkout from a page is limited to 30 orders an hour per IP address.

Callbacks

Callback Elements Called with
onSelect destination-picker: (code, plan); plans, trip-offer: (plan) The choice
onCheckout plans, trip-offer, booking-banner The order, before redirecting. false stops the redirect.
onOpen booking-banner The quote
onLoad esim-status The eSIM
onError all An Error with message (shown to the traveller too), code and status

Styling

Elements inherit the page's font and render in a .tdo container. Set the brand with appearance or CSS variables on the host element:

Variable appearance key
--tdo-color color Buttons, selected tiles, links
--tdo-on onColor Text on the colour
--tdo-radius radius Corners
--tdo-font font Font family (default: inherit)

Elements are responsive and accessible (buttons, ARIA states, progress bar for usage). Test keys show a small "Test" badge.

Sessions

Without a session, an element shows public prices to anyone and asks the traveller for their email. An element session, created by your server with your secret key, signs what the page may not decide on its own:

curl -X POST https://terudo.com/api/partner/v1/element_sessions \
  -H "Authorization: Bearer sk_live_…" -H "Content-Type: application/json" \
  -d '{
        "discount_percent": 10,
        "reference": "visa-48213",
        "client_email": "[email protected]",
        "trip": { "destination": "MA", "start_date": "2026-12-03", "end_date": "2026-12-09", "profile": "normal" },
        "return_url": "https://www.your-agency.example/bookings/48213",
        "locale": "fr",
        "metadata": { "booking_id": "48213" }
      }'
# → { "object": "element_session", "client_token": "…", "expires_at": "…", "session": { … } }
  • discount_percent: client discount 0–15 (default 5), taken from your commission.
  • reference: your booking or file id; the order carries it, and webhooks with it.
  • client_email, return_url, locale, trip, metadata: prefilled and trusted.
  • Your member rate applies when your account has it.

Pass client_token as data-session on the script or session in Terudo({...}). It lasts two hours: create it when you render the page.

Test mode

pk_test_… keys work exactly like live ones but create sandbox sales: the pay page simulates the payment, the eSIM is not a real one, nothing is billed. The demo key pk_test_terudo_demo_public shows real data but refuses checkout (demo_key). See Testing.

Content Security Policy

Allow script-src https://terudo.com, connect-src https://terudo.com and img-src https://terudo.com.

Errors

A failed element shows a short message in place (in the element's language) and calls onError. Common codes: unauthorized (key unknown or revoked), forbidden (page origin not listed on the key), invalid_trip (dates), unknown_plan, demo_key (checkout with the demo key), rate_limited.

Raw calls

terudo.api(path, { method, query, body }) calls the public routes with your key (and session): destinations, plans, quotes, checkout, esims/<id>. It returns a promise of the JSON. Useful to build your own interface on Terudo's data; the checkout still happens on terudo.com.