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.jswindow.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: ".*"window.location.pathname. If it does not match, this configuration block is skipped entirely.sourceLanguagestringDefault: document.documentElement.lang or "en"TRANSLATE, that choice restores the original text instead of calling the server.targetsstring (CSS selector)Default: "body"body once per page; use a narrower selector (e.g. article) if you only want certain regions.urlMappingobjectDefault: { targetLanguage: "language", triggerActions: "actions" }?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)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 languagesdefaultLanguagestringDefault: browser / page langcommentstring (any)onAfterInitialize() => voidDefault: no-opActions
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: —SUMMARIZE, TRANSLATE). Must be supported by your backend. Built-in button labeling uses translations only for SUMMARIZE and TRANSLATE.targetChildFilterstring (CSS selector)Default: "" (empty)targetChildIgnoreFilterstring (CSS selector)Default: ""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: —getButtonHTML({ currentlySelectedLanguage, translatedLabel }) => stringDefault: star icon + label (summarize) / globe icon + label (translate)translatedLabel is already localized.onActionStart / onActionFinishasync callbacksDefault: spinner on default actions{ 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: ""wrapperPositioning"before" | "after"Default: "before"getWrapperLeadingHTML / getWrapperTrailingHTML({ currentlySelectedLanguage }) => stringDefault: ""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 viadisplay: none;) - Result panel (summary / non-replacing stream):
resultPanelStyle,resultPanelAdditionalStyle,resultPanelClass - Translated text restoration:
originalTextElementClassmarks hidden spans that store original text when the server uses the replace-in-place strategy.
Language dropdown
getLanguageOptionHTML({ languageCode, languageLabel, currentlySelectedLanguage }) => stringDefault: languageLabel only<option> body.onLanguageChange({ language, previousLanguage, languageDropdown, actions }) => voidDefault: no-opactions (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
pathFilter: ".*"Regular expression tested against the pathname. ".*" matches all paths so this block runs site-wide.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.targets: "body"One widget is mounted per matching element—here, the document body, so typically a single toolbar on the page.actions: [ ... ]Each entry becomes a button. Order in the array is left-to-right in the toolbar.action: "SUMMARIZE"Button label and API action name for summarization (backend must support it).targetChildFilter: ""Empty means: treat each target element itself as the root for gathering text, not a narrower child selector.targetChildIgnoreFilter: ""Empty means: do not skip any subtrees; navigation and footer text are included unless you add selectors here.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.