Back to all docs

BeMyWords with Tilda (and other hosted page builders)

A complete integration guide for Tilda and similar hosted CMSes (Wix, Webflow, Squarespace) where you can paste a <script> tag but can't run a build pipeline.

Shape of the integration:

  1. Mark the project as Script mode in BeMyWords (Settings → Integration).
  2. Paste a single <script> tag into the site's head — the script swaps page text into the visitor's chosen language on every page load.
  3. Use Konami code (↑↑↓↓←→←→BA) on the live page to open the in-page editor and add or edit translations. Source text is the translation key, so there's no naming step.
  4. Opt into auto-translate per target language so new strings get AI-translated the moment they're harvested.

No build step. No GitHub Actions. No redeploy. Edits land in visitors' browsers on their next page load.


Prerequisites

  • A Tilda site (or any hosted page builder that lets you inject a script tag into the head).
  • A BeMyWords workspace with a project. Set Integration → Mode to "Script (Tilda, hosted sites)" under Settings → Integration.
  • A Personal Access Token for the project (Project → Settings → API keys → Personal access tokens) — only needed when editing; visitors don't need one.

1. Copy the embed snippet

In the BeMyWords dashboard, open the project and click Integrate (or Settings → Integration → "Open Integrate page").

You'll see a snippet that looks like this:

<script src="https://www.bemywords.no/bw-editor/trigger.js"
        data-project-id="<your-project-uuid>"
        data-public-read="true"
        defer></script>

Paste this into the head of every page on your Tilda site. In Tilda, that's Site Settings → More → Insert HTML code to head. The same snippet works for every page — every string the site harvests lands in one shared namespace, so you don't need to set data-namespace.

The Integrate page shows a live install indicator that turns green within seconds once the script is loaded by any visitor.

2. Add a locale switcher

Drop this anywhere on the page where you want a language dropdown to appear:

<div data-bw-switcher></div>

The script will fill it with a <select> populated from the project's enabled languages. Picking a language stores the choice and reloads the page.

The chosen language is remembered in localStorage (not a cookie — nothing to declare in a cookie banner), so it carries across every page the visitor opens. Links don't need ?lang= appended; the script reads the stored preference on each load.

If you'd rather build your own switcher, just have it set the ?lang= query parameter — the script picks that up, applies it, and persists it. The resolution order is ?lang= → URL prefix (/en/, /nb-NO/) → stored preference → <html lang>. A ?lang= link stays shareable: opening it persists that language for the recipient's later navigation too.

Right-to-left languages

When the visitor's language is right-to-left (Arabic, Hebrew, Persian, Urdu, …), the script also sets dir="rtl" on <html>, so the whole page mirrors. Switching back to a left-to-right language restores the page's original direction. No extra setup is needed — note that absolutely-positioned Tilda blocks may need manual RTL tweaks in Tilda's editor, since dir only mirrors text flow and logical CSS.

3. Harvest your page strings

Open any page on your site and type the Konami code:

↑ ↑ ↓ ↓ ← → ← → B A

The editor mounts in a right-side panel. Paste your Personal Access Token when prompted.

Click the ↺ Sync page strings button in the editor header (only visible when the source language is active). The editor harvests every text node, attribute (alt, title, aria-label, placeholder), and the value of submit, button, and reset inputs on the page, then creates one source-language row per unique string in BeMyWords. The source text is the translation key — no slug naming, no dot-paths.

You can also click any text on the page to jump to it in the sidebar, or double-click to edit it inline.

4. Auto-translate

Under Settings → Integration, tick the target languages you want auto-translated. As soon as new source strings land — whether via Sync, inline edit, or the API — BeMyWords schedules a debounced (5-second) AI pass for each opted-in language. The translations land as ai_draft status, immediately visible to visitors who load the page in that language.

Brand-new source strings always auto-translate. Edits to an existing source string only retranslate that string's now-stale target translations when the project's Re-translate edited strings setting (same Integration pane) is enabled — and even then only ai_draft translations are replaced; human-approved translations are left for manual drift review.

You can review and approve drafts in the normal translate UI, or just leave them — drafts are public by design in script mode.

Nightly site sync (no editor needed)

If you'd rather not open the in-page editor to pick up new content, set your site's root URL under Settings → Integration → Nightly site sync. Each night at 02:00 UTC, BeMyWords fetches your sitemap.xml, crawls every listed page, harvests any new source strings, and auto-translates them through the same pipeline as the ↺ Sync button. New content is then localized within a day with no manual step. Leave the field blank to keep harvesting manual.

5. How visitors see edits

The dictionary endpoint serves with ETag + must-revalidate. Every page load conditional-GETs the dictionary; the server returns 304 Not Modified (a few hundred bytes of headers) when nothing changed, and 200 with the new body when an edit landed. Visitors get edits on their next page load, with no CDN purge step.

API endpoints used in script mode

If you're rolling your own client, these are the unauthed endpoints the trigger script uses:

Endpoint Purpose
GET /api/<project_id>/dictionary/<lang>/<namespace> Flat { "source text": "translated text" } JSON. Sent with If-None-Match for cheap revalidation.
GET /api/<project_id>/public_info Minimal { source_language, enabled_languages } for the locale-switcher widget.
POST /api/<project_id>/install_ping Liveness signal — fires once per browser tab session per project. Powers the dashboard's install indicator. No PII.

And one authed endpoint used by the in-page editor's Sync button:

Endpoint Purpose
POST /api/<project_id>/sync_page_strings/<namespace> Bulk-create source rows. Body: { "source_strings": ["string 1", "string 2", ...] }. Idempotent and concurrency-safe — strings that already exist, including ones created by a simultaneous sync, are skipped.

All rate-limited via rack-attack.

Things that won't work in script mode

  • GitHub redeploy — not relevant; the dashboard hides the Redeploy tab automatically.
  • CSV / file imports — those paths still work, but slug-shaped keys defeat the source-text-as-key convention. Avoid mixing modes on the same project.
  • Pre-build language detection on the server — Tilda renders pages in the source language; the script swaps to the visitor's locale client-side. Visitors see a brief flash of the source language only on cold-cached first paint; warm cache + ETag revalidation makes subsequent loads instant.