Toolaby Wall

Your website

Connect your website to your workspace, so its pages can show the buyer's account and sell your tools.

toolaby-web.js is a script your website loads from your workspace. It gives your pages the buyer's account: an account button, content shown by sign-in state or by what the buyer owns, checkout, trials and the customer portal.

This page covers connecting your site and adding the script. Website components covers <toolaby-user> and the data-toolaby-* attributes; Website JavaScript covers window.Toolaby, React and Next.js.

Before you begin

  • A tool on your workspace, with its plans set under Pricing.
  • A website you can edit, and for the proxy, a server route you can add.
  • On Live, the Pro plan: your own pages and the proxy are Pro features. On Test every feature is on. See Plans.

1. Choose how your site connects

A page can see who is signed in only when the buyer's session reaches it. There are three ways. The script picks the one that applies; you never set it.

WayWhereWhat it needsThe session on your site
Your domainTest and LiveYour site on the same domain as your workspace's addressThe cookie on your workspace's address, which the browser sends because your page is on the same site
ProxyTest and LiveA route on your server that forwards to the Wall with a secretAn HttpOnly cookie on your own domain that no script can read
DevelopmentTest onlyNothing: any site, localhost includedA token your page keeps in its own storage

With none of them on Live, the page cannot see the buyer. It says so in the console, and every button opens the hosted pages instead: sign-in, checkout and the account page all still work, as links. Your domain is the way for production. The proxy is for a site whose domain cannot hold your workspace's address.

Toolaby.state.mode says which way a page is using: cookie, proxy, dev or link.

What works in each way

Your domainProxyDevelopmentNone (link)
<toolaby-user>YesYesYesAn Account link
Content by state (data-toolaby-signed-in, -signed-out, -owns)YesYesYesNeither shown: who is signed in is unknown
Checkout, trial, customer portalYesYesYesThe hosted pages, as links
A sign-in form of your own: data-toolaby-signin with an email fieldSends the link from your pageOpens the hosted sign-in pageOpens the hosted sign-in pageOpens the hosted sign-in page
A sign-in page of your own (sign-in-url)YesOpens; its sign-in goes through the hosted pageThe sameNot reached
Toolaby.session()The sign-in library's session{ user }{ user }null

Through a proxy or in development, sign-in always passes through the hosted sign-in page: that is where the one-time code that brings the session to your site is made.

2. Connect your site

Do one of the three.

With your domain

  1. Under Configure → Domain, verify an address such as accounts.example.com.
  2. Serve your pages on the same registrable domain: example.com or www.example.com for accounts.example.com.
  3. Under Configure → Your own pages, add each origin your pages are served from, such as https://www.example.com. Up to five.
  4. Load the script from that address, on every page that uses it:
<script src="https://accounts.example.com/client/toolaby-web.js" defer></script>

When it worked, Toolaby.state.mode is cookie on your pages.

Through a proxy

For a site that cannot share your workspace's domain. Your server forwards one path, /__toolaby, to the Wall.

  1. Under Configure → Your own pages → Proxy, select Make a proxy secret. It is shown once; the Wall keeps only its hash. Put it in your server's environment as TOOLABY_PROXY_SECRET.
  2. Under the same heading, add your site's origin, such as https://www.example.com. It may be any domain.
  3. Add the route the dashboard shows, filled in with your workspace's address. In Next.js it is app/__toolaby/[...path]/route.ts. It uses web-standard requests, so the same function runs in Remix, SvelteKit, Hono, Cloudflare Workers, Deno and Bun.
  4. Load the script through the proxy, from your own domain:
<script src="/__toolaby/client/toolaby-web.js" defer></script>

When it worked, Toolaby.state.mode is proxy.

The route sends the Wall five request headers (accept, accept-language, content-type, origin, user-agent) and the Wall's own cookie, never your site's other cookies or its Authorization header. It passes back only the Wall's own cookie, so nothing from the Wall can overwrite a cookie of yours. It adds the secret, its own address and the buyer's IP address, which the Wall trusts only when the secret is right, and then only for your workspace's own limits. It reads the address from x-real-ip, which Vercel and nginx set; behind Cloudflare, send cf-connecting-ip instead. A request with a wrong secret, or from an origin that is not listed, is refused with a 401. Through a proxy the Wall answers only what the script calls: the site's endpoints and the sign-in handshake. Anything else is a 404. The route sends only to the Wall's address: a path that names another host, such as /__toolaby//example.com/, is a 404 before anything is sent.

After sign-in, the session reaches your site as __Host-toolaby.session: HttpOnly, SameSite=Lax, Secure, and on your host alone, so no other host of your domain — a blog, a shop, anything with scripts of its own — can set one in its place. It works only through your proxy, on the site's endpoints: sent anywhere else, it is no session. A route file copied before 25 September 2026 keeps __Secure-toolaby.session, scoped to /__toolaby; replace it to move to the new cookie. Through the proxy, a request that changes something must come from your site's own pages: one from another origin is a 403. Select Replace secret to make a new one; the old one stops working at once. Revoke refuses every request through the proxy.

A buyer already signed in on your workspace who selects Sign in on your site comes straight back, signed in. A buyer who arrives at the sign-in from anywhere else, such as a link in a message, is asked Continue to your site first.

In development

On the Test Wall, the script works on any site with no setup: localhost, a preview deployment, a site you have not given a domain yet. Load it from your workspace's Test address, the one Configure → Domain shows:

<script src="https://quiet-otter-4172.toolaby.app/test/client/toolaby-web.js" defer></script>

When it worked, Toolaby.state.mode is dev. Signing in works like this:

  1. The page makes a random secret, keeps it in its own storage, and opens the sign-in page with its hash (PKCE).
  2. The sign-in page names your site and marks it Test mode.
  3. After signing in, the buyer confirms Continue to your site on a page of the Wall that cannot be shown inside another page.
  4. The page receives a one-time code in its address's fragment, which browsers never send to a server, and removes it at once.
  5. The page exchanges the code, with its secret, for a session token. The code works once, for two minutes, and only with that secret.

The token works on the endpoints a page needs (the account and what it holds, checkout, the trial, the customer portal and sign-out) and on nothing else. A script on your page can read it, which is why this exists only on Test. Live never accepts it: use your domain or a proxy there.

3. Add the account button

<toolaby-user></toolaby-user>

Signed out, it is a Sign in button; signed in, the buyer's picture with a menu. The script reads the buyer's account when the page loads, and again when the page becomes visible, at most once every ten seconds, so signing in or out in another tab shows here too. See Website components for everything it takes.

4. Sell from your page

<button data-toolaby-checkout="word-count">Buy</button>
<div data-toolaby-owns="word-count" hidden>Thanks for buying Word Count.</div>

See Website components for checkout, trials and the customer portal, and Website JavaScript to do the same from code.

When a page always shows the buyer as signed out

Open the browser's console: the script says which way it is using and why.

What you seeCause
Toolaby: … is not on the same domain as … and has no proxyOn Live, the page has none of the three ways. Connect your domain, or add a proxy.
A CORS errorThe page's origin is not listed under Configure → Your own pages, or the page calls a route the script does not: a listed page reaches the session, a sign-in link, signing out, entitlements, the portal, a trial and checkout. The origin is the scheme, the host and the port, exactly.
This request did not come from a page that may make it (403)A request that changes something for the signed-in buyer came from a page that is not listed, and not through your proxy.
After signing in, the buyer lands on the account page instead of your pageThe page is under no listed origin and no proxy origin, and it is not the Test Wall.
This proxy is not recognised (401)The proxy's secret is wrong or was replaced, or its origin is not listed under Proxy.
This sign-in has expired or was started somewhere elseThe one-time code was used, took more than two minutes, or came back to a different browser than the one that started the sign-in. Sign in again.

Security

  • Your domain: the session cookie stays on your workspace's address. Your page never holds it; the browser sends it with each request the script makes. The Wall answers with your page's origin only if it is listed, and only on the routes the script calls; a request that changes something for the buyer from any other page is refused, even one on another workspace's address.
  • Proxy: the session is an HttpOnly cookie on your domain, scoped to the proxy's path. The Wall trusts a proxied request only with the right secret, compared as a hash in constant time, and from a listed origin. It answers only the site's endpoints through a proxy, and the buyer's address a proxy names counts only toward your workspace's limits.
  • Development: Test only. The code is single use, lasts two minutes, travels in the fragment and is bound by PKCE to a secret the page keeps, so a code seen by anyone else is worth nothing. The buyer confirms the site first. The token reaches only the endpoints a page needs.
  • Everywhere: the sign-in page returns a buyer only to a listed origin, a proxy origin or, on Test, a site the buyer confirmed. Any other next goes to the account page. A site session never reaches the endpoints that change an account.
  • Content by state is shown by the browser. data-toolaby-owns hides an element from a buyer who does not hold the tool; it does not keep its content from them. Keep what must stay private on your server, and check there: see Sync customers.

See also

On this page