Embed the forecast widget.

Show a TUBR sales forecast on your own web pages with one server call and one script tag.
The TUBR widget shows a sales forecast for one outlet on your own web pages. This guide tells you how to add the widget to a page.
The widget shows ten days of sales. Past days show the actual sales. Today and future days show the forecast. The card shows the forecast for the selected day.

Terms in this guide

Term
Meaning
Secret key
A key that TUBR gives to your company. It starts with tbp:. Keep it on your server only.
Outlet code
The code that identifies one outlet. It has the form integration:id, for example square:EXAMPLE123.
Grant
A short-lived code that lets one page view open the widget. The widget can use a grant one time only.
Origin
The scheme, host and port of a web page, for example https://dashboard.example.com.
Mint
To ask the TUBR API for a new grant.

Before you start

Make sure that you have these items:
  • A secret key from TUBR.
  • The outlet code of each outlet that you want to show. You can show only the outlets that you send to TUBR.
  • A server that can make HTTPS requests. The secret key must stay on this server.

How it works

  • Your server mints a grant for one outlet with the secret key.
  • Your server puts the grant into the page that it sends to the browser.
  • The TUBR script on the page uses the grant to open the widget in an iframe.
The secret key never goes to the browser. The grant is not a secret, because it is short-lived and works one time only.

Step 1: Send your origins to TUBR

The widget opens only on pages that TUBR knows. Each origin that shows the widget must be on your allow-list.
  • Make a list of each origin that will show the widget.
  • Include the origins of your test and staging sites.
  • Send the list to TUBR through the contact page.
  • Wait until TUBR tells you that the list is active.

Step 2: Mint a grant on your server

Mint a new grant each time that your server makes a page with the widget. Do not keep a grant for a second page view.
  • Send a POST request to https://api.prod.tubr.live/partner/v1/grant.
  • Put your secret key in the Authorization header, after the word Bearer.
  • Put the outlet code in the JSON body.
  • Read the grant value from the response.
Request · bash
curl -X POST https://api.prod.tubr.live/partner/v1/grant \ -H "Authorization: Bearer $TUBR_PARTNER_KEY" \ -H "Content-Type: application/json" \ -d '{"outlet_code": "square:EXAMPLE123", "ttl_seconds": 120}'
Response · json
{ "grant": "eyJhbGciOiJFZERTQSIsImtpZCI6ImVtYmVkLTIwMjYtMDgifQ...", "expires_at": "2026-06-10T09:32:00+00:00", "expires_in": 120 }

Request body

Field
Required
Meaning
outlet_code
Yes
The outlet code of the outlet to show.
ttl_seconds
No
How long the grant stays valid, in seconds. The default is 60. The minimum is 30 and the maximum is 600.

Errors

Status
Body
Cause and action
400
invalid_ttl_seconds
ttl_seconds is not a number. Send a whole number of seconds.
400
missing_outlet_code
The body has no outlet code. Add outlet_code to the body.
401
The secret key is not correct, or TUBR revoked it. Examine the Authorization header.
403
outlet_mismatch
TUBR does not have this outlet from you. Examine the outlet code.
429
You minted too many grants. The limit is 60 per minute. Wait for the number of seconds in the Retry-After header.
Warning
Do not mint a grant in the browser. That request contains your secret key, and any visitor can read it.
Warning
Mint grants only for users who signed in to your application. If any visitor can make your server mint grants, that visitor can use all of your rate limit.

Step 3: Add the script tag to your page

  • Find the position on your page where the widget must show.
  • Add the script tag below at that position.
  • Replace {{ grant }} with the grant from step 2.
html
<script src="https://cdn.tubr.live/embed/v1.js" data-grant="{{ grant }}" data-theme="auto" data-width="100%" ></script>
The script adds the widget immediately after the script tag. You can add the async or defer attribute to the tag.

Step 4: Test the page

  • Open the page in a browser on an origin from your allow-list.
  • Make sure that the chart and the forecast card show.
  • Reload the page. Make sure that the widget shows again.
  • If the widget does not show, read Troubleshooting.

Optional parameters

Set these attributes on the script tag. TUBR controls all other parts of the widget, and updates them for you.
Attribute
Required
Default
Meaning
data-grant
Yes
The grant that your server minted for this page view. The widget uses it one time only.
data-theme
No
auto
The colour theme. Use auto to follow the light or dark setting of the device. Values: light, dark, auto.
data-width
No
100%
The width of the widget, as a CSS width value such as 100%, 480px or 32rem. The widget sets its own height.

Theme

This is the widget with data-theme="light":
This is the widget with data-theme="dark":

Width

In a narrow space, the forecast card moves below the chart. The widget changes its height to fit. Before the widget loads, it keeps a minimum height of 120 pixels.

Events

The script sends these events to your page. You do not have to listen for them.
Event
Meaning
tubr:embed:error
The widget cannot show. It hides its space on the page. event.detail.message gives the reason.
tubr:embed:grant-request
The session is near its end. Mint a new grant and give it to event.detail.respond(grant).

Record errors

When the widget cannot show, it hides its space on your page. Your layout does not need a change. You can record the reason for your own monitoring.
html
<script> window.addEventListener("tubr:embed:error", (event) => { // The widget has already hidden itself. Record the reason. console.warn("TUBR widget:", event.detail.message); }); </script>

Keep the widget open for a long time

A session lasts 15 minutes. After 12 minutes, the widget asks your page for a new grant.
  • Make an endpoint on your server that mints a grant, as in step 2.
  • Listen for the tubr:embed:grant-request event.
  • Call your endpoint and give the new grant to event.detail.respond.
html
<script> window.addEventListener("tubr:embed:grant-request", async (event) => { // Your own endpoint. It mints a grant on your server, as in step 2. const response = await fetch("/tubr-grant"); const { grant } = await response.json(); event.detail.respond(grant); }); </script>
If you do not listen for this event, the widget stops at the end of the session. The widget shows again when the visitor reloads the page.

Example project

The example project is a minimal Node.js server that does steps 2 and 3. It has no dependencies. Read its README to run it.

Versions

  • Always load the script from https://cdn.tubr.live/embed/v1.js. Do not keep a copy.
  • TUBR adds fixes and improvements to this version without a change to your page.
  • A change that is not compatible goes to a new URL. The old URL continues to work.

Troubleshooting

Problem
Possible cause
Action
The error event gives missing_grant.
The script tag has no data-grant value.
Make sure that your server puts the grant into the tag.
The widget shows on the first page view only.
Your server or a cache sends the same grant again.
Mint a new grant for each page view. Do not cache pages that contain a grant.
The widget does not show on one site only.
The origin of that site is not on your allow-list.
Send the origin to TUBR, as in step 1.
The grant request returns 403.
The outlet code is not an outlet that you send to TUBR.
Examine the outlet code.
The widget stops after some minutes.
Your page does not answer the grant request.
Listen for the grant request event.
If the problem continues, contact TUBR. Give the time of the problem and the error message.
Built from tubr-tech-expo df57270c88 and tubr-tech-python e7a6d5a8dd.