Web SDKs
JavaScript
Create links and show an open-in-app banner from any website, with or without a build step.
@becklinks/web is the Beck Links package for websites. With plain JavaScript, or from a <script> tag with no build step, it does two things:
- Create links from the browser, for example a share button that makes a link to the product the visitor is looking at.
- Show an "Open in the app" banner to visitors on a phone, with a button that goes through your Beck Links link, so the app opens on the right screen (or the store opens, and the link survives the install).
It has no dependencies, sets no cookies, and writes nothing to storage unless you tell it the visitor agreed (consentGranted). If you use React, Next.js or Vue, start with React, Next.js or Vue: they wrap this package.
Get it: @becklinks/web on npm
Before you start#
You need a project with your app configured (Android, iOS) and its publishable key. A publishable key (pk_test_… or pk_live_…) is made to sit in a web page. A secret key (sk_…) must never: the SDK refuses to start with one, and the API refuses it when it arrives from a browser.
Then tell Beck Links which websites may use the key:
- Open the dashboard, your project, Settings.
- In the card of the environment you use (Test or Live), find Web origins.
- Add one origin per line, for example
https://example.comandhttps://www.example.com. An origin is the scheme and host (and port) without a path or wildcard.http://localhost:5173is accepted for local development. - Select Save origins. A change reaches the browsers within a minute.
Without this step every browser call fails with origin_not_allowed. Test and live environments keep separate lists.
Install#
npm install @becklinks/webOr load it from a CDN with a script tag (see Script tag only).
Show the open-in-app banner#
import { createBeckLinks } from '@becklinks/web';
const beckLinks = createBeckLinks({ publishableKey: 'pk_live_…' });
beckLinks.showBanner({
url: 'https://acme.becklinks.com/summer',
title: 'Open in the Acme app',
description: 'Faster checkout and your saved items.',
buttonLabel: 'Open',
iconUrl: 'https://acme.com/app-icon.png',
});The banner:
- appears only on phones (Android and iOS, including iPadOS). Desktop visitors see nothing; limit it further with
platforms: ['ios']or['android']; - is added to the end of
<body>inside a shadow root, so your page styles do not break it, and it follows the visitor's light or dark setting andprefers-reduced-motion; - escapes your text:
titleanddescriptionare plain text, never HTML; - hides after the close button is used. By default it comes back on the next page view. Pass
consentGranted: truetocreateBeckLinksonce the visitor accepted optional storage, and the dismissal is remembered fordismissDaysdays (default 7).
| Option | Meaning |
|---|---|
url | The Beck Links URL to open. Required, https (or http localhost). |
title | The first line. Required. |
description | A second, smaller line. |
buttonLabel | Text of the open button. Default Open. |
closeLabel | Accessible name of the close button. Default Close banner. |
iconUrl | Square app icon, an https image. |
platforms | ['ios', 'android'] by default. |
position | 'bottom' (default) or 'top'. |
dismissDays | Days a dismissed banner stays hidden (needs consentGranted). |
onOpen | Called when the open button is used. |
onDismiss | Called when the close button is used. |
showBanner returns a handle with dismiss() and destroy(), or null when the banner does not apply (a desktop, an unlisted platform, a recent dismissal, or no document during server rendering).
Create a link from the browser#
try {
const link = await beckLinks.createLink({
deepLinkPath: '/product/42',
data: { sku: 'A-1' },
campaign: 'share-button',
utm: { source: 'website', medium: 'share' },
});
await navigator.share({ url: link.url });
} catch (error) {
if (error instanceof BeckLinksError && error.code === 'origin_not_allowed') {
// This website is not listed under Web origins.
}
}Browser link creation needs the sdk:links scope on the publishable key, and a link is always created on your environment's own link host. The browser cannot choose the host or the short path; if you need that, create the link on your server (Next.js has a helper, or use the REST API).
| Field | Meaning |
|---|---|
deepLinkPath | The route the app opens, starting with /. Required. |
data | JSON for your app, up to 4 KB. Everyone with the link can read it: no secrets. |
campaign | The key of an existing campaign. |
utm | source, medium, content, term, creative. |
expiresAt | A Date or ISO string in the future. |
The result has id, url, status, createdAt and expiresAt. A call is retried on network failures and 5xx answers (twice by default) with the same idempotency key, so a retry never makes a second link.
Errors#
Every failure is a BeckLinksError with a kind (configuration, network, api, unexpected_response), and for api errors the stable code, status, requestId and, when the API asks you to wait, retryAfterSeconds.
code | Meaning and fix |
|---|---|
origin_not_allowed | The website is not under Web origins. Add it in the environment settings. |
invalid_api_key | The key is wrong, revoked or from another environment. |
insufficient_scope | The key may not create links from clients (sdk:links). |
validation_failed | A field is wrong; the message names it. |
rate_limited | Too many calls from this address or key. Wait retryAfterSeconds. |
When the browser blocks a call before the API answers (for example an origin that is not listed), the page only sees a failed request, so the SDK reports kind: 'network' and its message points you to Web origins. Open the browser's network panel to see the exact reason.
See the full list in the error reference.
Script tag only#
For a static site, add the script and describe the banner with attributes. No JavaScript of your own is needed:
<script
src="https://cdn.jsdelivr.net/npm/@becklinks/web@0/dist/becklinks.min.js"
data-key="pk_live_…"
data-banner-url="https://acme.becklinks.com/summer"
data-banner-title="Open in the Acme app"
data-banner-description="Faster checkout and your saved items."
data-banner-button="Open"
data-banner-icon="https://acme.com/app-icon.png"
data-banner-position="bottom"
data-consent="granted"
defer
></script>Leave data-consent out until the visitor agreed to optional storage. The script also defines window.BeckLinks with createBeckLinks and BeckLinksError, for your own code. Pin the major version in the URL (@0) and review the changelog before you move to a new one.
Options#
| Option | Default | Meaning |
|---|---|---|
publishableKey | required | pk_test_… or pk_live_…. |
apiUrl | https://api.becklinks.com | Change for a local API; https or http on localhost only. |
consentGranted | false | Allows remembering a dismissed banner in localStorage. |
timeoutMs | 10000 | Per attempt, 1000 to 60000. |
maxRetries | 2 | Retries after a network failure or 5xx, 0 to 5. |
Privacy#
The SDK sends the publishable key, the link you ask for and the usual headers a browser adds, with credentials: 'omit' and no referrer. It sets no cookie, writes no storage without consentGranted, runs no tracking and sends no device identifier. Visits and installs from web links are counted by the redirect service when the link is opened, as for any other link.
Verify it works#
- Add your origin under Web origins for the Test environment and use a
pk_test_…key. - Open your page on a phone (or in the browser's device mode): the banner appears. On a desktop browser it does not, by design.
- Run
await beckLinks.createLink({ deepLinkPath: '/' })in the console. It returns a link on your-testhost; open it in the dashboard under Links to see it, tagged as created by the SDK. - Open the link on a phone with your test app installed. The app opens on the route you set. If not, the Link Tester and Troubleshooting show why.