Embed widget configuration

The embed script ( v1.js) reads window.textSenseConfig and runs initTextSense when it loads. Your config can be a single object or an array of objects. Each object is a separate rule block: every block whose pathFilter matches the current path runs on its own (so keep patterns disjoint, or use a single block, unless you intentionally want multiple toolbars).

For sites that need different toolbar placement or styles on different sections, you can use an array of blocks—typically one pathFilter per area—with shared options like languages and tailored styling per block.

Minimal shape

// Set before loading v1.js
window.textSenseConfig = {
pathFilter: ".*",
sourceLanguage: "en",
targets: "body",
actions: [
{ action: "SUMMARIZE", targetChildFilter: "", targetChildIgnoreFilter: "" },
{ action: "TRANSLATE", targetChildFilter: "", targetChildIgnoreFilter: "" }
]
};
// Or multiple URL-specific rules (array)
window.textSenseConfig = [
{ pathFilter: "/news/.*", /* ... */ },
{ pathFilter: "/about/?$", /* ... */ }
];
// Optional preserve translation across pages: rewriteSameOriginLink: "preserveTranslation"
// (built-in linker only adds query params when mostRecentAction is TRANSLATE — see docs)
// rewriteSameOriginLink: ({ url, anchor, currentLanguage, mostRecentAction, ... }) => { ... }

General options

pathFilterstring (RegExp)Default: ".*"
Tested against window.location.pathname. If it does not match, this configuration block is skipped entirely.
sourceLanguagestringDefault: document.documentElement.lang or "en"
ISO language code for the page source text. Used when calling the API and to detect when the user selects the source language in the dropdown—for TRANSLATE, that choice restores the original text instead of calling the server.
targetsstring (CSS selector)Default: "body"
Elements that receive the widget. For each match, a wrapper (toolbar + optional result area) is created. Often body once per page; use a narrower selector (e.g. article) if you only want certain regions.
urlMappingobjectDefault: { targetLanguage: "language", triggerActions: "actions" }
Maps query parameter names to behaviors. If set, ?language=de (by default) pre-selects German; ?actions=SUMMARIZE,TRANSLATE auto-clicks those buttons shortly after init (comma-separated, case-insensitive).
rewriteSameOriginLink(context) => string | void | "preserveTranslation"Default: undefined (disabled)
When set to a function, the script calls it for each eligible same-origin link to decide a new href (so you can carry Text-Sense-related URL state on navigation). Links must be same-origin http: / https: and are scanned across the whole document. context is { url, anchor, sourceLanguage, currentLanguage, triggerActionsFromURL, urlMapping, mostRecentAction }—use url (a URL) as the baseline for each link. mostRecentAction is the uppercase name of the last toolbar action that finished on this page load, or null before any action runs (unchanged when only the language dropdown changes). Return a non-empty string to set the new href (relative paths resolve against the link's origin); return undefined, null, or "" to leave that anchor unchanged. The first time a link is touched, the script stores data-text-sense-original-href so later passes (for example after a language change) do not keep appending duplicate query params. The hook runs after init, whenever any toolbar language dropdown changes, after any toolbar action runs, and on new nodes via a debounced MutationObserver (links only inside closed shadow roots are not seen). Shortcut: "preserveTranslation" enables the implementation bundled in v1.js (internal, not exposed globally): it sets urlMapping.targetLanguage and ensures urlMapping.triggerActions includes TRANSLATE on the link only when mostRecentAction is TRANSLATE, so the next page auto-runs translation; define both keys under urlMapping.
languagesstring[]Default: all built-in languages
Restricts the language dropdown to these codes (must exist in the script's built-in list). Order is preserved.
defaultLanguagestringDefault: browser / page lang
Initial selection for the dropdown when no URL override is present. Normalized to two-letter codes.
commentstring (any)
Not used by the script. You can use it as a private note in your own config source.
onAfterInitialize() => voidDefault: no-op
Called after all targets for this block have been processed and panels attached.

Actions

actions is an array of action objects. Each entry can include a pathFilter if you want that button to appear only on certain paths (regex on pathname). If every action is filtered out for the current URL, no panel is added.

actionstringDefault:
Action name sent to the API (for example SUMMARIZE, TRANSLATE). Must be supported by your backend. Built-in button labeling uses translations only for SUMMARIZE and TRANSLATE.
targetChildFilterstring (CSS selector)Default: "" (empty)
When non-empty, only descendants of each target matching this selector contribute text. When empty, the target element itself is used as the root for text collection.
targetChildIgnoreFilterstring (CSS selector)Default: ""
Elements to exclude (and all text inside them). Applied after targetChildFilter. Prefer this over trying to encode exclusions only in :not() on the include filter—parent nodes may still pull excluded areas in.
pathFilterstring (RegExp)Default:
Optional per-action pathname filter; if present, the action is omitted when it does not match.
getButtonHTML({ currentlySelectedLanguage, translatedLabel }) => stringDefault: star icon + label (summarize) / globe icon + label (translate)
Returns the button's inner HTML. For summarize and translate, translatedLabel is already localized.
onActionStart / onActionFinishasync callbacksDefault: spinner on default actions
Receives { target, actions, action, languageDropdown, currentlySelectedLanguage, translatedLabel }. Use to customize loading states; defaults add a spinning icon around the label.

Where the toolbar is inserted

By default the wrapper is placed before or after each target node. If you set an anchor, it is inserted relative to that element instead. Older names panelAnchor / panelPosition still work as aliases.

wrapperAnchorstring (CSS selector)Default: ""
First matching element on the page; the wrapper is inserted before or after it (not inside it).
wrapperPositioning"before" | "after"Default: "before"
Insert the wrapper before or after the anchor (or the target if no anchor).
getWrapperLeadingHTML / getWrapperTrailingHTML({ currentlySelectedLanguage }) => stringDefault: ""
Extra HTML injected inside the wrapper, before or after the toolbar row. Useful for disclaimers or links.

Styling hooks

Most elements combine a base *Style string with an optional *AdditionalStyle string and a *Class class name. Defaults favor a compact flex toolbar and a light gray result panel.

  • Wrapper: wrapperStyle, wrapperAdditionalStyle, wrapperClass
  • Toolbar row: panelStyle, panelAdditionalStyle, panelClass
  • Action buttons: buttonStyle, buttonAdditionalStyle, buttonClass
  • Language select: selectStyle, selectAdditionalStyle, selectClass
  • “In” label between buttons and dropdown: inBetweenTextStyle, inBetweenTextAdditionalStyle, inBetweenTextClass (hidden in many site configs via display: none;)
  • Result panel (summary / non-replacing stream): resultPanelStyle, resultPanelAdditionalStyle, resultPanelClass
  • Translated text restoration: originalTextElementClass marks hidden spans that store original text when the server uses the replace-in-place strategy.

Language dropdown

getLanguageOptionHTML({ languageCode, languageLabel, currentlySelectedLanguage }) => stringDefault: languageLabel only
Customizes each <option> body.
onLanguageChange({ language, previousLanguage, languageDropdown, actions }) => voidDefault: no-op
Fires when the user changes the select; you can inspect actions (each has a button reference after init) to trigger work.

Examples

Walkthroughs for common setups. Each tab shows a full config, a short overview, then what each important setting does.

window.textSenseConfig = {
pathFilter: ".*",
sourceLanguage: "en",
targets: "body",
actions: [
{
action: "SUMMARIZE",
targetChildFilter: "",
targetChildIgnoreFilter: "",
},
{
action: "TRANSLATE",
targetChildFilter: "",
targetChildIgnoreFilter: "",
},
],
};

Runs the summarize and translate toolbar on every page whose path matches the filter. Text is collected from the full document body, and both actions apply to the same scope.

Settings in this example

  1. pathFilter: ".*"Regular expression tested against the pathname. ".*" matches all paths so this block runs site-wide.
  2. sourceLanguage: "en"Declares the language of the original page. The API uses it for requests; choosing this language in the dropdown restores original text instead of translating again.
  3. targets: "body"One widget is mounted per matching element—here, the document body, so typically a single toolbar on the page.
  4. actions: [ ... ]Each entry becomes a button. Order in the array is left-to-right in the toolbar.
  5. action: "SUMMARIZE"Button label and API action name for summarization (backend must support it).
  6. targetChildFilter: ""Empty means: treat each target element itself as the root for gathering text, not a narrower child selector.
  7. targetChildIgnoreFilter: ""Empty means: do not skip any subtrees; navigation and footer text are included unless you add selectors here.
  8. action: "TRANSLATE"Second button for full translation into the language chosen in the dropdown.

Advanced: full placement override

Replacing addTextSenseToTarget lets you control mounting entirely. The default implementation creates the wrapper, wires buttons to processTarget / restoreTarget, and respects filters and URL auto-actions. Only override if you need behavior that cannot be expressed with anchors and styles.

How results appear

The client streams Server-Sent Events from your API. An early UI Strategy event tells the widget whether to stream into the result panel below the toolbar (show_in_panel) or replace original text nodes in place (replace_original_text). That choice comes from the server, not from the static config file.