# Inline AI Docs — full text > Inline AI is the answer engine for digital publishers. It adds on-site conversational AI grounded in the publisher's own content and turns every reader question into first-party data, ad inventory, and editorial intelligence. Every documentation page below, concatenated as Markdown. Index: https://docs.getinline.io/llms.txt --- # Inline AI - Documentation Source: https://docs.getinline.io/ Inline AI adds AI search, key takeaways, in-content questions, and a conversational sidebar to any website. Pick the product you want to integrate with. - [Widget SDK](/introduction): Embed AI features on your site with a single `` tag. Auto mode renders placements from your dashboard config, no JavaScript required. - [Partner API](/partner-api/overview): Server-to-server REST API for programmatic access to publisher data, AI-generated content, and engagement metrics. Private preview. --- # Widget SDK overview Source: https://docs.getinline.io/introduction The Widget SDK is a single JavaScript file you load on your page. It exposes `window.InlineAI` and renders one or more **placements**: individual AI-powered features like a search overlay, an article summary, or a sticky sidebar panel. Placements render automatically from your dashboard configuration, or you can mount them explicitly from your own JavaScript. - [Quickstart](/quickstart): Add the widget to your page in under 2 minutes. - [Integration modes](/integration-modes): Auto, programmatic, or hybrid. Compare tradeoffs side by side. ## Placement types Placements are the individual AI features the SDK renders on your page. There are seven types: | Placement | Description | Needs a target element | | --- | --- | :-: | | `Widget` | Sticky sidebar panel with a floating trigger button | No | | `SearchFab` | Floating action button for search (fixed to the viewport) | No | | `SearchEmbed` | Full-width search input bar embedded inline | Yes | | `SearchIcon` | Compact search button that opens the search overlay | Yes | | `KeyTakeaways` | AI-generated summary block for the page's content | Yes | | `SingleQuestion` | In-content question pills distributed across article paragraphs | Yes | | `BasicEmbed` | Embedded AI content block | Yes | `Widget` and `SearchFab` attach to the page body by default and don't need a target element. They're the fastest way to get AI features on a page. The other five placements require you to specify where they should render using an element ID, a CSS selector, or dynamic attribute matching. ## Integration modes The SDK supports three integration modes. All three use the same script tag; the mode is determined by what (if anything) you push into the command queue before the script loads. - Auto mode: Add the script tag and do nothing else. Placements render from your dashboard config. No JavaScript required. - Programmatic mode: Call `init()` and `mount()` each placement yourself. You decide what renders, where, and when. - Hybrid mode: Auto rendering plus access to SDK events and imperative `open()` / `close()`. ## Key capabilities - **Search overlay:** `SearchEmbed`, `SearchIcon`, and `SearchFab` all open the same AI-powered overlay. You can also open it programmatically with `window.InlineAI.open()`. - **Key takeaways:** reads the page content and renders a concise AI summary. Drop it in a sidebar or above the article body. - **In-content questions:** injects clickable question pills into your article, distributed across paragraphs. Limit and strategy are both configurable. - **Sticky sidebar widget:** a persistent conversational panel. A floating trigger button opens a sidebar where readers ask follow-ups scoped to the page content. --- # Add the widget to your site Source: https://docs.getinline.io/quickstart The fastest way to get Inline AI on your site is **auto mode**: paste one ` ``` > The `?key=` parameter is required. The SDK will not initialize without a valid Publisher ID. ## 2. Load the page That's the integration. On the next page load the SDK reads your dashboard config and renders every enabled placement. By default, the Widget sidebar appears with a floating trigger button in the bottom corner of the page. > Don't see the Widget? Open the Inline AI dashboard, confirm the **Widget** placement is enabled for the publisher, then hard-refresh the page. ## 3. (Optional) Tune placements from the dashboard Every placement's behavior (position, copy, breakpoints, which pages it runs on) is controlled from the dashboard. You don't need to touch your site's code again to add a search bar, turn on key takeaways, or tweak the Widget trigger position. Reach out to the Inline AI team if you need help configuring a placement. --- ## Need more control? Auto mode covers most integrations. Reach for a different mode only when you need JavaScript-level control: - [Programmatic mode](/integration-modes#programmatic-mode): Call `mount()` for each placement yourself. Best for SPAs, dynamic content, or when you want full control over what renders and where. - [Hybrid mode](/integration-modes#hybrid-mode): Auto rendering plus access to SDK events. Forward `SearchOpen` / `WidgetOpen` to your analytics, or trigger the overlay from your own button. ## Next steps - [Placement types](/placements/overview): The seven AI features the SDK renders: what each one does and how to configure it. - [Injection targets](/configuration/injection-targets): Control exactly where targeted placements appear using IDs, CSS selectors, or dynamic matching. - [Events](/events/overview): Subscribe to lifecycle, search, and widget events to integrate with your site. - [Command queue](/guides/command-queue): Buffer SDK calls made before the script loads using the `window.InlineAI.cmd` queue. --- # Add Inline with an AI agent Source: https://docs.getinline.io/install Inline AI is a **client-side JavaScript SDK** that adds on-site conversational AI to any website that runs JavaScript. Installing it is one ` ``` > The script is loaded from `getinline.tech` (the widget CDN) — keep that domain as-is. The `?key=` parameter is required. That's the whole integration for **auto mode**: on the next page load the SDK reads the publisher's dashboard configuration and renders every enabled placement. No JavaScript to write. ## 2. Pick the right path for the site Match the site to the canonical guide instead of guessing: - [Static HTML / WordPress / Ghost / Webflow / any CMS](/quickstart): Use auto mode — paste the snippet once and manage placements from the dashboard. This is the quickstart. - [React / Vue / Next.js / other SPA](/integration-modes): Single-page apps should use programmatic mode and call `mount()` per placement. See integration modes. - [Placement names & types](/api/enums): The enum of placement types (Widget, Search FAB, Search Embed, Search Icon, Key Takeaways, Single Question, Basic Embed) and other constants. - [Init / mount options](/configuration/mount-options): Parameters for `init()` and `mount()` — targeting, breakpoints, and per-placement config. - [Events](/events/overview): Subscribe to lifecycle, search, and widget events via `window.InlineAI` to wire Inline into the site's own analytics. - [Command queue](/guides/command-queue): Buffer SDK calls made before the script finishes loading using `window.InlineAI.cmd`. ## 3. Verify the install 1. Load any page on the site. 2. The Widget placement appears with a floating trigger button in the bottom corner by default. 3. Don't see it? Open the [dashboard](https://tools.getinline.tech/), confirm the **Widget** placement is enabled for the publisher, then hard-refresh. ## Notes for agents - **No Partner API for signup yet.** Onboarding (creating a publisher, getting a Publisher ID) is done in the dashboard, not programmatically. The install itself is fully client-side. - A machine-readable index of every docs page is at [/llms.txt](https://docs.getinline.io/llms.txt); the full docs as one file are at [/llms-full.txt](https://docs.getinline.io/llms-full.txt). Append `.md` to any docs page path for its raw Markdown (e.g. `/quickstart` → `/quickstart.md`; the home page is at `/index.md`). --- # Integration modes Source: https://docs.getinline.io/integration-modes All three modes use the same embed snippet. The mode is determined by what (if anything) you push into `window.InlineAI.cmd` before the script loads. ## Auto mode The default. The SDK reads your dashboard configuration and renders placements automatically. You write no JavaScript. **Pick auto mode when:** - You want the fastest setup. - You're happy managing placements from the dashboard. - You don't need to react to SDK events from your page code. ```html ``` That's the entire integration. ## Programmatic mode Programmatic mode activates when you push an `['init', ...]` command into the queue before the SDK loads (or call `window.InlineAI.init()` directly after it loads). In this mode the SDK does **not** auto-render from your dashboard; you call `mount()` for every placement yourself. **Pick programmatic mode when:** - You need precise control over which placements render and where. - You're building a single-page app whose DOM changes after load. - You want to integrate placement lifecycle with your own application state. ```html
``` Then paste the embed snippet **after** the queue setup: ```html ``` For runtime mount/unmount patterns (SPA routing, dynamic content), see the [programmatic control guide](/guides/programmatic-control). ## Hybrid mode Hybrid mode combines auto rendering with direct SDK access. Placements render from your dashboard just like auto mode, but you can subscribe to events and call `open()` / `close()` from your own code. Activate hybrid mode by pushing a **function callback** into the queue, without calling `init()`. The SDK passes itself as the first argument when it's ready. **Pick hybrid mode when:** - You want auto rendering but need to forward Inline AI events to your own analytics. - You want to open the search overlay from your own nav button or keyboard shortcut. ```html ``` Then the embed snippet: ```html ``` > Do not call `init()` in hybrid mode. If `init()` is present in the command queue, the SDK switches to programmatic mode and stops auto-rendering placements. ## At a glance | Feature | Auto | Programmatic | Hybrid | | --- | :-: | :-: | :-: | | Auto-renders from dashboard config | Yes | No | Yes | | JavaScript required | No | Yes | Yes | | Call `init()` | No | Yes | No | | Call `mount()` for placements | No | Yes | No | | Access SDK events (`on()`) | No | Yes | Yes | | Open/close overlays programmatically | No | Yes | Yes | | Inspect mounted placements (`getPlacements()`) | No | Yes | Yes | ## Next steps - [Command queue](/guides/command-queue): How the queue buffers calls made before the script loads. - [Programmatic control](/guides/programmatic-control): Mount/unmount patterns, SPA routing, overlay control. - [Events reference](/events/reference): Every event the SDK emits, with payload shapes. - [Placement types](/placements/overview): The seven AI features you can render. --- # Placements Source: https://docs.getinline.io/placements/overview Placements are the individual AI features the Widget SDK renders on your page. Each one has a specific purpose, from a sticky conversational sidebar to in-content question pills, and is rendered either automatically from your dashboard configuration or explicitly with `window.InlineAI.mount()`. ## All placement types | Placement | Enum value | Description | Target required | |-----------|------------|-------------|:---------------:| | Widget | `widget` | Sticky sidebar panel with a floating trigger button | No | | Search FAB | `search-fab` | Floating action button for search, attaches to the page body | No | | Search embed | `search-embed` | Full-width search input bar rendered inside a container | Yes | | Search icon | `search-icon` | Compact icon/button that opens the search overlay | Yes | | Key takeaways | `key-takeaways` | AI-generated summary block for article content | Yes | | Single question | `single-question` | In-content question pills distributed across paragraphs | Yes | | Basic embed | `basic-embed` | Generic AI content block rendered into a container | Yes | ## Body-level vs targeted placements **Body-level placements** (`Widget` and `SearchFab`) attach directly to `document.body` and need no target element. They're what auto mode renders by default, and they're the fastest path to AI on a page. **Targeted placements** (everything else) render inside a DOM element you specify. Pass a string element ID, a CSS selector, or a dynamic element matcher. ```javascript // Body-level: no target needed window.InlineAI.mount(window.InlineAI.Placement.Widget); window.InlineAI.mount(window.InlineAI.Placement.SearchFab); // Targeted: target is required window.InlineAI.mount(window.InlineAI.Placement.SearchEmbed, 'search-container'); window.InlineAI.mount(window.InlineAI.Placement.KeyTakeaways, { selector: '.article-sidebar' }); ``` See [injection targets](/configuration/injection-targets) for the full targeting syntax and [mount options](/configuration/mount-options) for options shared across placement types. ## Placement pages - [Widget](/placements/widget): Sticky sidebar panel with a floating trigger. The default in auto mode. - [Search FAB](/placements/search-fab): Floating search button. No target required. - [Search embed](/placements/search-embed): Full-width search input embedded in a container. - [Search icon](/placements/search-icon): Compact button that opens the search overlay. - [Key takeaways](/placements/key-takeaways): AI-generated summary block for articles. - [Single question](/placements/single-question): In-content question pills distributed across paragraphs. - [Basic embed](/placements/basic-embed): Generic AI content block for any container. --- # Widget Source: https://docs.getinline.io/placements/widget The **Widget** placement is a sticky, conversational AI panel with a floating trigger button. Readers click the trigger to open a sidebar and ask questions scoped to the page content. It's a body-level placement, so it attaches directly to `document.body` and needs no target. The Widget is the default placement in [auto mode](/integration-modes#auto-mode). If you've pasted the embed snippet, this is the AI feature that appears on your site. ## Mounting programmatically In [programmatic mode](/integration-modes#programmatic-mode), a single `mount()` call is all it takes: no target, no required options. ```javascript window.InlineAI.mount(window.InlineAI.Placement.Widget); ``` The call returns a placement ID you can pass to `unmount()` later. See the [programmatic control guide](/guides/programmatic-control) for mount/unmount patterns and SPA routing. ## Opening and closing from your own code Use `window.InlineAI.open()` and `window.InlineAI.close()` with `OverlayTarget.Widget` to drive the sidebar from your own UI, for example a CTA button or a keyboard shortcut. ```javascript // Open the sidebar window.InlineAI.open(window.InlineAI.OverlayTarget.Widget); // Close it window.InlineAI.close(window.InlineAI.OverlayTarget.Widget); ``` ```javascript document.getElementById('open-assistant').addEventListener('click', function () { window.InlineAI.open(window.InlineAI.OverlayTarget.Widget); }); ``` > If you're driving the Widget from your own button, you may want to hide the default floating trigger. Toggle the trigger visibility from your Inline AI dashboard. ## Events The SDK emits `WidgetOpen` and `WidgetClose` when the sidebar opens and closes. Use them to sync your own UI state, for example to pause a video when the panel opens. ```javascript var { Events } = window.InlineAI; window.InlineAI.on(Events.WidgetOpen, function () { console.log('Widget panel opened'); }); window.InlineAI.on(Events.WidgetClose, function () { console.log('Widget panel closed'); }); ``` See the [events reference](/events/reference#widget-events) for payload shapes and the full event catalog. --- # Search FAB Source: https://docs.getinline.io/placements/search-fab The search FAB (floating action button) placement renders a persistent, floating button that users can click to open the AI search overlay. Unlike the [search embed](/placements/search-embed) and [search icon](/placements/search-icon) placements, the search FAB is a body-level placement: it attaches directly to `document.body` and does not require you to designate a container element. You control its horizontal position and offsets from the page edges using the `fabPosition` option. ## Mounting the placement Because the search FAB is a body-level placement, you can omit the target argument entirely. Pass `Placement.SearchFab` and an options object: ```javascript window.InlineAI.mount( window.InlineAI.Placement.SearchFab, undefined, { fabPosition: { horizontalPosition: window.InlineAI.FabPosition.Right, rightOffset: '20px', bottomOffset: '24px', }, } ); ``` Passing `undefined` as the target makes it clear the placement does not need one. You can also omit the target argument entirely: ```javascript window.InlineAI.mount(window.InlineAI.Placement.SearchFab); ``` > The search FAB attaches to `document.body`. It renders over your page content and does not affect your page layout. ## FAB position options Use the `fabPosition` object to control where the button appears. - `fabPosition.horizontalPosition` (FabPosition): Horizontal position of the FAB. Use `window.InlineAI.FabPosition.Left` (`"left"`), `window.InlineAI.FabPosition.Right` (`"right"`), or `window.InlineAI.FabPosition.Center` (`"center"`). - `fabPosition.leftOffset` (string): Distance from the left edge of the viewport as a CSS value (e.g. `"20px"`). Applies when `horizontalPosition` is `Left` or `Center`. - `fabPosition.rightOffset` (string): Distance from the right edge of the viewport as a CSS value (e.g. `"20px"`). Applies when `horizontalPosition` is `Right` or `Center`. - `fabPosition.bottomOffset` (string): Distance from the bottom edge of the viewport as a CSS value (e.g. `"24px"`). - `fabPosition.maxWidth` (string): Maximum width of the FAB button as a CSS value. ## Search overlay options The search FAB shares search overlay options with the other search placements. - `placeholder` (string): Placeholder text shown in the search input when the overlay opens. - `overlayType` (OverlayType): How the search overlay appears. `window.InlineAI.OverlayType.Modal` (`"modal"`) or `window.InlineAI.OverlayType.Drawer` (`"drawer"`). - `backdropOpacity` (number): Opacity of the overlay backdrop, between `0` and `1`. - `openOverlayOn` (OpenOverlayOn): When to open the overlay: `window.InlineAI.OpenOverlayOn.Focus` or `window.InlineAI.OpenOverlayOn.QuerySubmit`. - `shouldShowSuggestedQuestions` (boolean): Whether to show suggested questions in the overlay. - `suggestedQuestionsMode` (SuggestedQuestionsMode): Display mode for suggested questions: `"animated"` or `"static"`. - `typographySource` (TypographySource): Typography inheritance: `"inherit-from-website"` or `"inherit-from-theme"`. - `overlayBreakpoints` (OverlayBreakpointConfig[]): Per-viewport overrides for overlay settings. ## Positioning examples ```javascript Bottom-right (default) window.InlineAI.mount(window.InlineAI.Placement.SearchFab, undefined, { fabPosition: { horizontalPosition: window.InlineAI.FabPosition.Right, rightOffset: '20px', bottomOffset: '24px', }, }); ``` ```javascript Bottom-left window.InlineAI.mount(window.InlineAI.Placement.SearchFab, undefined, { fabPosition: { horizontalPosition: window.InlineAI.FabPosition.Left, leftOffset: '20px', bottomOffset: '24px', }, }); ``` ```javascript Bottom-center window.InlineAI.mount(window.InlineAI.Placement.SearchFab, undefined, { fabPosition: { horizontalPosition: window.InlineAI.FabPosition.Center, bottomOffset: '24px', }, }); ``` > If your page has a fixed footer or bottom navigation bar, increase `bottomOffset` to prevent the FAB from overlapping it. For unmounting, SPA routing, and command-queue usage, see the [programmatic control guide](/guides/programmatic-control). --- # Search embed Source: https://docs.getinline.io/placements/search-embed The search embed placement renders a full-width search input bar directly inside a container element you specify. When a user interacts with it, the SDK opens a search overlay. You control the input shape, when the overlay opens, and how it appears (as a modal or a drawer). This placement is a good fit for prominent search areas like page headers, hero sections, or dedicated search pages. ## Mounting the placement Pass `Placement.SearchEmbed` as the first argument to `mount()`, a target as the second, and an options object as the third. ```javascript window.InlineAI.mount( window.InlineAI.Placement.SearchEmbed, 'search-container', { placeholder: 'Search for answers...', shape: window.InlineAI.InputShape.RoundedRectangle, openOverlayOn: window.InlineAI.OpenOverlayOn.Focus, } ); ``` The target can be an element ID string, a CSS selector object, or a dynamic matcher. The call returns a placement ID string that you can pass to `unmount()` later. > The search embed placement requires a target. If you want a search button that floats over the page without a container, use the [Search FAB](/placements/search-fab) placement instead. ## Targeting the container ```javascript // By element ID (shorthand) window.InlineAI.mount(window.InlineAI.Placement.SearchEmbed, 'header-search'); // By CSS selector window.InlineAI.mount(window.InlineAI.Placement.SearchEmbed, { selector: '[data-role="search"]', }); // By dynamic element matching window.InlineAI.mount(window.InlineAI.Placement.SearchEmbed, { dynamic: { tagName: 'div', attributeName: 'class', attributeValue: 'search-area' }, }); ``` ## Options - `placeholder` (string): Placeholder text displayed inside the search input before the user types. - `shape` (InputShape): Shape of the search input. Accepts `window.InlineAI.InputShape.Pill` (`"pill"`) or `window.InlineAI.InputShape.RoundedRectangle` (`"rounded-rectangle"`). - `openOverlayOn` (OpenOverlayOn): When to open the search overlay. Use `window.InlineAI.OpenOverlayOn.Focus` (`"onFocus"`) to open as soon as the input receives focus, or `window.InlineAI.OpenOverlayOn.QuerySubmit` (`"onQuerySubmit"`) to open only after the user submits a query. - `overlayType` (OverlayType): How the search overlay appears. `window.InlineAI.OverlayType.Modal` (`"modal"`) centers it over the page; `window.InlineAI.OverlayType.Drawer` (`"drawer"`) slides it in from the side. - `backdropOpacity` (number): Opacity of the backdrop behind the overlay, as a number between `0` and `1`. - `shouldShowSuggestedQuestions` (boolean): Whether to show suggested questions in the search overlay. - `suggestedQuestionsMode` (SuggestedQuestionsMode): Display mode for suggested questions. `"animated"` cycles through them; `"static"` shows them all at once. - `typographySource` (TypographySource): Where the placement inherits its typography. `"inherit-from-website"` uses your site's fonts; `"inherit-from-theme"` uses the Inline AI theme fonts. - `overlayBreakpoints` (OverlayBreakpointConfig[]): Override overlay settings at specific viewport widths. Each entry can set `overlayType`, `backdropOpacity`, and `openOverlayOn`. The most specific (narrowest) matching breakpoint wins. ## Full example ```javascript window.InlineAI.mount( window.InlineAI.Placement.SearchEmbed, 'search-container', { placeholder: 'Search for answers...', shape: window.InlineAI.InputShape.RoundedRectangle, openOverlayOn: window.InlineAI.OpenOverlayOn.Focus, overlayType: window.InlineAI.OverlayType.Modal, backdropOpacity: 0.6, overlayBreakpoints: [ { maxViewportWidth: 767, overlayType: window.InlineAI.OverlayType.Drawer, backdropOpacity: 1.0, }, ], } ); ``` > Use `overlayBreakpoints` to show a modal on desktop and a full-screen drawer on mobile. Set `maxViewportWidth: 767` on the mobile breakpoint and `minViewportWidth: 768` on the desktop breakpoint. For unmounting, SPA routing, and command-queue usage, see the [programmatic control guide](/guides/programmatic-control). --- # Search icon Source: https://docs.getinline.io/placements/search-icon The search icon placement renders a small, self-contained search button inside a target element. Unlike the search embed, it does not display a visible text input. Instead, it shows an icon, a label, or both. When a user clicks it, the search overlay opens. This placement works well in navigation bars, toolbars, and any space-constrained area where a full input bar would not fit. ## Mounting the placement Pass `Placement.SearchIcon` as the first argument to `mount()`, followed by the target element and an options object. ```javascript window.InlineAI.mount( window.InlineAI.Placement.SearchIcon, 'nav-search', { label: 'Search', shouldShowIcon: true, buttonWidth: '120px', buttonHeight: '40px', } ); ``` The target can be a string element ID, a CSS selector, or a dynamic matcher object. The call returns a placement ID you can pass to `unmount()`. > The search icon placement requires a target element. If you want a floating button that is not anchored to any container, use the [Search FAB](/placements/search-fab) placement instead. ## Targeting the container ```javascript // By element ID window.InlineAI.mount(window.InlineAI.Placement.SearchIcon, 'nav-search'); // By CSS selector window.InlineAI.mount(window.InlineAI.Placement.SearchIcon, { selector: '.site-header .search-trigger', }); ``` ## Options ### Button appearance - `label` (string): Text label displayed on the button. If omitted, the button shows only the icon (if `shouldShowIcon` is `true`). - `shouldShowIcon` (boolean): Whether to display the search icon on the button. Defaults to showing the icon. - `buttonWidth` (string): Width of the button as a CSS value (e.g. `"120px"`, `"100%"`). - `buttonHeight` (string): Height of the button as a CSS value (e.g. `"40px"`). - `maxWidth` (string): Maximum width of the button as a CSS value. - `maxHeight` (string): Maximum height of the button as a CSS value. ### Search overlay - `placeholder` (string): Placeholder text shown in the search input when the overlay opens. - `overlayType` (OverlayType): How the search overlay appears. `window.InlineAI.OverlayType.Modal` centers it over the page; `window.InlineAI.OverlayType.Drawer` slides it in from the side. - `backdropOpacity` (number): Opacity of the backdrop behind the overlay, between `0` and `1`. - `openOverlayOn` (OpenOverlayOn): When to open the search overlay. `window.InlineAI.OpenOverlayOn.Focus` opens it on focus; `window.InlineAI.OpenOverlayOn.QuerySubmit` opens it after query submission. - `shouldShowSuggestedQuestions` (boolean): Whether to display suggested questions in the search overlay. - `suggestedQuestionsMode` (SuggestedQuestionsMode): How to display suggested questions: `"animated"` cycles through them, `"static"` shows them all. - `typographySource` (TypographySource): Typography inheritance mode: `"inherit-from-website"` or `"inherit-from-theme"`. - `overlayBreakpoints` (OverlayBreakpointConfig[]): Per-viewport overrides for `overlayType`, `backdropOpacity`, and `openOverlayOn`. ## Full example ```javascript window.InlineAI.mount( window.InlineAI.Placement.SearchIcon, 'nav-search', { label: 'Search', shouldShowIcon: true, buttonWidth: '120px', buttonHeight: '40px', overlayType: window.InlineAI.OverlayType.Modal, backdropOpacity: 0.5, } ); ``` For unmounting, SPA routing, and command-queue usage, see the [programmatic control guide](/guides/programmatic-control). --- # Key takeaways Source: https://docs.getinline.io/placements/key-takeaways The key takeaways placement renders an AI-generated summary of your page content inside a target element. It reads the article or long-form content on the page and produces a concise list of key points, giving readers a quick overview before they dive in. This placement is well suited for sidebars, article introductions, or any position near the top of your content where a summary adds value. ## Mounting the placement Pass `Placement.KeyTakeaways` and a target to `mount()`. The target is typically a CSS selector or an element ID. ```javascript window.InlineAI.mount( window.InlineAI.Placement.KeyTakeaways, { selector: '.article-sidebar', location: window.InlineAI.InjectionLocation.Prepend, maxWidth: '400px', } ); ``` The call returns a placement ID you can pass to `unmount()` later. > The key takeaways placement requires a target. The SDK generates the summary based on the page's content, so the placement works best on pages with substantial readable text. ## Targeting the container ```javascript Element ID window.InlineAI.mount(window.InlineAI.Placement.KeyTakeaways, 'article-summary'); ``` ```javascript CSS selector window.InlineAI.mount(window.InlineAI.Placement.KeyTakeaways, { selector: '.article-sidebar', }); ``` ```javascript Dynamic element matching window.InlineAI.mount(window.InlineAI.Placement.KeyTakeaways, { dynamic: { tagName: 'aside', attributeName: 'class', attributeValue: 'post-sidebar', elementIndex: 0, }, }); ``` ## Positioning and sizing - `location` (InjectionLocation): Where to insert the placement relative to the target element: - `window.InlineAI.InjectionLocation.Above`: sibling before the target - `window.InlineAI.InjectionLocation.Below`: sibling after the target - `window.InlineAI.InjectionLocation.Prepend`: first child of the target - `window.InlineAI.InjectionLocation.Append`: last child of the target - `width` (string): Width of the placement container as a CSS value (e.g. `"100%"`, `"400px"`). - `maxWidth` (string): Maximum width of the placement container as a CSS value. - `height` (string): Height of the placement container as a CSS value. - `maxHeight` (string): Maximum height of the placement container as a CSS value. - `breakpoints` (BreakpointConfig[]): Responsive breakpoints with `minViewportWidth`, `maxViewportWidth`, `width`, and `height` per entry. ## Examples ```javascript Minimal window.InlineAI.mount(window.InlineAI.Placement.KeyTakeaways, 'article-summary'); ``` ```javascript Sidebar with max width window.InlineAI.mount(window.InlineAI.Placement.KeyTakeaways, { selector: '.article-sidebar', location: window.InlineAI.InjectionLocation.Prepend, maxWidth: '400px', }); ``` ```javascript Prepend to article window.InlineAI.mount(window.InlineAI.Placement.KeyTakeaways, { dynamic: { tagName: 'article' }, location: window.InlineAI.InjectionLocation.Prepend, width: '100%', }); ``` > Prepending the key takeaways block to your article container (using `InjectionLocation.Prepend`) places it above your content automatically, without needing a dedicated element in your HTML. For unmounting, SPA routing, and command-queue usage, see the [programmatic control guide](/guides/programmatic-control). --- # Single question Source: https://docs.getinline.io/placements/single-question The single question placement injects AI-generated question pills directly into your article content, distributing them across paragraphs as users scroll. Each pill presents a question related to the surrounding content; clicking it opens the search overlay with that question pre-filled. This placement is designed for long-form articles and blog posts where you want to prompt reader engagement at natural breakpoints in the text. ## Mounting the placement Pass `Placement.SingleQuestion` and a target to `mount()`. The target is typically a dynamic matcher pointing at your article container, since the SDK needs to traverse its child paragraphs to distribute pills. ```javascript window.InlineAI.mount( window.InlineAI.Placement.SingleQuestion, { dynamic: { tagName: 'article' }, injectionLimit: 3, injectionStrategy: window.InlineAI.InjectionStrategy.DistributeEvenly, } ); ``` The call returns a placement ID you can pass to `unmount()`. > The single question placement requires a target. The SDK injects pills as siblings to paragraph elements inside the target container. For best results, target the element that directly wraps your article body text. ## Targeting the container ```javascript Dynamic tag matching window.InlineAI.mount(window.InlineAI.Placement.SingleQuestion, { dynamic: { tagName: 'article' }, injectionLimit: 3, injectionStrategy: window.InlineAI.InjectionStrategy.DistributeEvenly, }); ``` ```javascript By element ID window.InlineAI.mount(window.InlineAI.Placement.SingleQuestion, 'article-body'); ``` ```javascript By CSS selector window.InlineAI.mount(window.InlineAI.Placement.SingleQuestion, { selector: '.post-content', injectionLimit: 5, }); ``` ## Injection options - `injectionLimit` (number): Maximum number of question pills to inject into the content. The SDK will not exceed this number regardless of how many paragraphs the article contains. - `injectionStrategy` (InjectionStrategy): How to distribute pills across the content: - `window.InlineAI.InjectionStrategy.Default` (`"default"`): places pills at the beginning of the content. - `window.InlineAI.InjectionStrategy.DistributeEvenly` (`"distribute-evenly"`): spaces pills evenly across the available paragraphs. - `injectionSelectorOffset` (number): Offset for the first injection point. A value of `1` skips the first paragraph and starts injecting from the second. - `typographySource` (TypographySource): Typography inheritance mode for the question pills: `"inherit-from-website"` or `"inherit-from-theme"`. ## Sizing and positioning - `location` (InjectionLocation): Where to inject each pill relative to its target paragraph: `"above"`, `"below"`, `"prepend"`, or `"append"`. - `width` (string): Width of each pill container as a CSS value. - `maxWidth` (string): Maximum width of each pill container. - `breakpoints` (BreakpointConfig[]): Responsive breakpoints for controlling when and at what size pills render. ## Examples ```javascript Evenly distributed, limited to 3 window.InlineAI.mount(window.InlineAI.Placement.SingleQuestion, { dynamic: { tagName: 'article' }, injectionLimit: 3, injectionStrategy: window.InlineAI.InjectionStrategy.DistributeEvenly, }); ``` ```javascript Skip the first paragraph window.InlineAI.mount(window.InlineAI.Placement.SingleQuestion, { selector: '.post-body', injectionLimit: 4, injectionStrategy: window.InlineAI.InjectionStrategy.DistributeEvenly, injectionSelectorOffset: 1, }); ``` ```javascript Default strategy window.InlineAI.mount(window.InlineAI.Placement.SingleQuestion, { dynamic: { tagName: 'article' }, injectionLimit: 2, injectionStrategy: window.InlineAI.InjectionStrategy.Default, }); ``` > `InjectionStrategy.DistributeEvenly` tends to produce the best engagement on long articles because it surfaces questions throughout the content rather than clustering them at the top. For unmounting, SPA routing, and command-queue usage, see the [programmatic control guide](/guides/programmatic-control). --- # Basic embed Source: https://docs.getinline.io/placements/basic-embed The basic embed placement renders an AI-powered content block inside a container element you specify. It is the most straightforward targeted placement: point it at a `div`, pass any sizing options you need, and the SDK handles the rest. Use it when you want to surface contextually relevant AI content in a sidebar, below an article, or anywhere else on your page. ## Mounting the placement Pass `Placement.BasicEmbed` and a target to `mount()`. The target can be a string element ID for the simplest case: ```javascript window.InlineAI.mount(window.InlineAI.Placement.BasicEmbed, 'content-sidebar'); ``` The call returns a placement ID string you can later pass to `unmount()`. > The basic embed placement requires a target. Make sure the target element exists in the DOM before calling `mount()`. If you are mounting after a dynamic page load, wait for the element to appear before mounting. ## Targeting the container You have three options for specifying the target element. ```javascript Element ID // Shorthand string: looks up by element ID window.InlineAI.mount(window.InlineAI.Placement.BasicEmbed, 'content-sidebar'); // Equivalent using the object form window.InlineAI.mount(window.InlineAI.Placement.BasicEmbed, { containerId: 'content-sidebar', }); ``` ```javascript CSS selector window.InlineAI.mount(window.InlineAI.Placement.BasicEmbed, { selector: 'main > aside:first-child', }); ``` ```javascript Dynamic element matching window.InlineAI.mount(window.InlineAI.Placement.BasicEmbed, { dynamic: { tagName: 'div', attributeName: 'class', attributeValue: 'content-area', elementIndex: 0, }, }); ``` ## Positioning and sizing Use the injection target object to control where the placement renders relative to its container and how large it should be. - `location` (InjectionLocation): Where to insert the placement relative to the target element. Options: - `"above"`: sibling before the target - `"below"`: sibling after the target - `"prepend"`: first child of the target - `"append"`: last child of the target Use `window.InlineAI.InjectionLocation` enum values (e.g. `InjectionLocation.Prepend`). - `width` (string): Width of the placement container as a CSS value (e.g. `"100%"`, `"320px"`). - `maxWidth` (string): Maximum width of the placement container as a CSS value. - `height` (string): Height of the placement container as a CSS value. - `maxHeight` (string): Maximum height of the placement container as a CSS value. - `breakpoints` (BreakpointConfig[]): Responsive breakpoints. Each entry can set `minViewportWidth`, `maxViewportWidth`, `width`, and `height`. The placement only renders when a breakpoint matches the current viewport. ## Examples ```javascript Minimal window.InlineAI.mount(window.InlineAI.Placement.BasicEmbed, 'content-sidebar'); ``` ```javascript With sizing and position window.InlineAI.mount(window.InlineAI.Placement.BasicEmbed, { selector: '.article-sidebar', location: window.InlineAI.InjectionLocation.Prepend, width: '100%', maxWidth: '360px', }); ``` ```javascript With responsive breakpoints window.InlineAI.mount(window.InlineAI.Placement.BasicEmbed, { containerId: 'inline-content', breakpoints: [ { minViewportWidth: 768, width: '360px' }, { maxViewportWidth: 767, width: '100%' }, ], }); ``` For unmounting, SPA routing, and command-queue usage, see the [programmatic control guide](/guides/programmatic-control). --- # Mount options Source: https://docs.getinline.io/configuration/mount-options The optional third argument to `mount()` is a `MountOptions` object that controls how a placement looks and behaves. Options are grouped by placement type: some apply to all search placements, others are exclusive to the search icon or floating action button. You can also configure how the search overlay opens and define per-viewport overrides with overlay breakpoints. ## Search placement options #### Search embed and FAB These options apply to `SearchEmbed` and `SearchFab` placements. They control the search input appearance, suggested questions, and overlay behavior. - `placeholder` (string): Placeholder text shown inside the search input before the user types. - `shape` (string): Shape of the search input field. Accepts `'pill'` or `'rounded-rectangle'` (or the `InputShape` enum values `InputShape.Pill` / `InputShape.RoundedRectangle`). - `shouldShowSuggestedQuestions` (boolean): When `true`, the SDK displays suggested questions below or alongside the search input. - `suggestedQuestionsMode` (string): Controls how suggested questions are displayed. Accepts `'animated'` (cycle through questions) or `'static'` (show all at once). - `typographySource` (string): Where the placement inherits its font styles from. Accepts `'inherit-from-website'` (matches the surrounding page) or `'inherit-from-theme'` (uses the Inline AI theme). Also available as `TypographySource.Website` / `TypographySource.Theme`. - `overlayType` (string): How the search results overlay appears. Accepts `'modal'` (centered dialog) or `'drawer'` (slides in from the side). Also available as `OverlayType.Modal` / `OverlayType.Drawer`. - `backdropOpacity` (number): Opacity of the backdrop behind the overlay. Accepts a value between `0` (fully transparent) and `1` (fully opaque). - `openOverlayOn` (string): When the search overlay opens. Accepts `'onQuerySubmit'` (opens after the user submits a query) or `'onFocus'` (opens as soon as the input is focused). Also available as `OpenOverlayOn.QuerySubmit` / `OpenOverlayOn.Focus`. ```javascript var { Placement, InputShape, OpenOverlayOn, OverlayType } = window.InlineAI; window.InlineAI.mount(Placement.SearchEmbed, 'search-container', { placeholder: 'Search for answers...', shape: InputShape.RoundedRectangle, shouldShowSuggestedQuestions: true, suggestedQuestionsMode: 'animated', overlayType: OverlayType.Modal, backdropOpacity: 0.6, openOverlayOn: OpenOverlayOn.Focus, }); ``` #### Search icon These options are exclusive to the `SearchIcon` placement: a compact button that opens the search overlay when clicked. - `label` (string): Text label displayed on the search button alongside or instead of the icon. - `shouldShowIcon` (boolean): When `true`, the search icon (magnifying glass) is shown in the button. Set to `false` to show only the label text. - `buttonWidth` (string): Width of the search button. Accepts any valid CSS size value (e.g. `'120px'`, `'8rem'`). - `buttonHeight` (string): Height of the search button. Accepts any valid CSS size value (e.g. `'40px'`, `'2.5rem'`). - `maxWidth` (string): Maximum width of the search button. Useful when the button is inside a fluid container. - `maxHeight` (string): Maximum height of the search button. ```javascript var { Placement } = window.InlineAI; window.InlineAI.mount(Placement.SearchIcon, 'nav-search', { label: 'Search', shouldShowIcon: true, buttonWidth: '120px', buttonHeight: '40px', }); ``` #### Search FAB The `SearchFab` placement is a floating action button that is not anchored to a specific container. Use `fabPosition` to control where it appears on the screen. - `fabPosition.horizontalPosition` (string): Horizontal anchor for the FAB. Accepts `'left'`, `'right'`, or `'center'`. Also available as `FabPosition.Left` / `FabPosition.Right` / `FabPosition.Center`. - `fabPosition.leftOffset` (string): Distance from the left edge of the viewport. Accepts any valid CSS length (e.g. `'20px'`). Applied when `horizontalPosition` is `'left'` or `'center'`. - `fabPosition.rightOffset` (string): Distance from the right edge of the viewport. Accepts any valid CSS length. Applied when `horizontalPosition` is `'right'` or `'center'`. - `fabPosition.bottomOffset` (string): Distance from the bottom edge of the viewport. Accepts any valid CSS length (e.g. `'24px'`). - `fabPosition.maxWidth` (string): Maximum width of the FAB button. ```javascript var { Placement, FabPosition } = window.InlineAI; window.InlineAI.mount(Placement.SearchFab, undefined, { fabPosition: { horizontalPosition: FabPosition.Right, rightOffset: '20px', bottomOffset: '24px', }, }); ``` > `SearchFab` and `Widget` are body-level placements; you do not need to pass a target element. Pass `undefined` as the second argument when you want to supply options without a target. ## Overlay breakpoints Overlay breakpoints let you override the overlay type, backdrop opacity, and open trigger at specific viewport widths. This is useful when you want a modal on desktop and a drawer on mobile. Each entry in `overlayBreakpoints` can specify `minViewportWidth`, `maxViewportWidth`, or both to define the range it applies to. When multiple breakpoints match the current viewport, the most specific one (narrowest range) wins. - `overlayBreakpoints` (OverlayBreakpointConfig[]): Array of viewport-specific overlay configuration overrides. Each item can include the following fields: Minimum viewport width in pixels for this breakpoint to apply. - `maxViewportWidth` (number): Maximum viewport width in pixels for this breakpoint to apply. - `overlayType` (string): Overlay type at this breakpoint. Accepts `'modal'` or `'drawer'`. - `backdropOpacity` (number): Backdrop opacity at this breakpoint (0–1). - `openOverlayOn` (string): Open trigger at this breakpoint. Accepts `'onQuerySubmit'` or `'onFocus'`. ```javascript var { Placement, OverlayType, OpenOverlayOn } = window.InlineAI; window.InlineAI.mount(Placement.SearchEmbed, 'search-container', { overlayType: OverlayType.Modal, backdropOpacity: 0.6, overlayBreakpoints: [ { minViewportWidth: 768, overlayType: OverlayType.Modal, backdropOpacity: 0.6, }, { maxViewportWidth: 767, overlayType: OverlayType.Drawer, backdropOpacity: 1.0, openOverlayOn: OpenOverlayOn.Focus, }, ], }); ``` > Set top-level `overlayType` and `backdropOpacity` as your defaults, then use `overlayBreakpoints` only to override the values that differ at certain viewport sizes. --- # Injection targets Source: https://docs.getinline.io/configuration/injection-targets The `target` parameter in `mount()` tells the SDK which DOM element to inject a placement into. You have three methods to choose from: a plain string shorthand for element IDs, a CSS selector for flexible matching, or dynamic tag-and-attribute rules for when stable IDs and classes aren't available. All three methods can be combined with positioning and sizing options to control exactly how the placement container appears on the page. ## Targeting methods #### Element ID The simplest way to specify a target is to pass the element's `id` attribute as a plain string. The SDK treats any string `target` as a `containerId` lookup; both forms below are equivalent. ```javascript // String shorthand (most common) window.InlineAI.mount(window.InlineAI.Placement.SearchEmbed, 'header-search'); // Explicit containerId object, identical behavior window.InlineAI.mount(window.InlineAI.Placement.SearchEmbed, { containerId: 'header-search' }); ``` ```html ``` > Use the string shorthand when you have a stable, unique element ID. It is the most concise option and is equivalent to passing `{ containerId: 'id' }`. #### CSS selector Pass any valid CSS selector via the `selector` field when you need to target an element without a unique ID, or when you want to match based on class, attribute, or DOM structure. ```javascript var { Placement } = window.InlineAI; // Class selector window.InlineAI.mount(Placement.KeyTakeaways, { selector: '.article-sidebar' }); // Attribute selector window.InlineAI.mount(Placement.SearchEmbed, { selector: '[data-role="search"]' }); // Structural selector window.InlineAI.mount(Placement.BasicEmbed, { selector: 'main > aside:first-child' }); ``` > When a selector matches more than one element, the SDK injects into the first match unless you combine it with `injectionLimit` or `injectionStrategy`. #### Dynamic matching Dynamic matching lets you specify a target by tag name plus an optional attribute name and value. This is useful for pages where element IDs and class names are generated dynamically or change between deploys. ```javascript window.InlineAI.mount(window.InlineAI.Placement.BasicEmbed, { dynamic: { tagName: 'div', attributeName: 'class', attributeValue: 'content-area', elementIndex: 0, }, }); ``` The `dynamic` object accepts the following fields: - `dynamic.tagName` (string): The HTML tag name to search for (e.g. `'div'`, `'article'`, `'section'`). This is the only required field. - `dynamic.attributeName` (string): The name of the attribute to match against (e.g. `'class'`, `'data-section'`). Omit to match any element with the given tag name. - `dynamic.attributeValue` (string): The expected value of `attributeName`. Required when `attributeName` is set. The match is exact (not a substring match). - `dynamic.elementIndex` (number): Selects the Nth element from all matches (0-indexed). Defaults to `0` (first match). Use this when multiple elements share the same tag and attribute. ## Positioning with `location` By default, the SDK appends the placement container as a child of the target element. You can change this with the `location` field using the `InjectionLocation` enum. ```javascript var { Placement, InjectionLocation } = window.InlineAI; window.InlineAI.mount(Placement.KeyTakeaways, { selector: '.sidebar', location: InjectionLocation.Prepend, }); ``` | Value | Behavior | |---|---| | `InjectionLocation.Above` | Insert as a sibling immediately before the target element | | `InjectionLocation.Below` | Insert as a sibling immediately after the target element | | `InjectionLocation.Prepend` | Insert as the first child inside the target element | | `InjectionLocation.Append` | Insert as the last child inside the target element (default) | You can also use the raw string values (`'above'`, `'below'`, `'prepend'`, `'append'`) in place of the enum. ## Sizing the placement container Control the dimensions of the injected container with `width`, `height`, `maxWidth`, and `maxHeight`. These accept any valid CSS size value. ```javascript window.InlineAI.mount(window.InlineAI.Placement.BasicEmbed, { selector: '.sidebar', width: '100%', maxWidth: '600px', height: 'auto', maxHeight: '400px', }); ``` > Sizing fields on the injection target control the placement **container** element. To size the placement contents themselves, see the width and height options available on individual placement types. ## Full example The example below combines all three targeting approaches with positioning: ```javascript var { Placement, InjectionLocation } = window.InlineAI; // Element ID: search bar in the header window.InlineAI.mount(Placement.SearchEmbed, 'header-search'); // CSS selector: key takeaways above the sidebar window.InlineAI.mount(Placement.KeyTakeaways, { selector: '.article-sidebar', location: InjectionLocation.Prepend, }); // Dynamic matching: first div with class "content-area" window.InlineAI.mount(Placement.BasicEmbed, { dynamic: { tagName: 'div', attributeName: 'class', attributeValue: 'content-area', elementIndex: 0, }, }); ``` --- # Breakpoints Source: https://docs.getinline.io/configuration/breakpoints Breakpoints let you adapt placement rendering to the current viewport width. The SDK supports two independent breakpoint systems: placement breakpoints, which control whether and at what size a placement container renders, and overlay breakpoints, which override how the search overlay behaves on different screen sizes. You can use either or both systems independently. ## Placement breakpoints Placement breakpoints are defined in the `breakpoints` array on the injection target (the second argument to `mount()`). Each entry specifies a viewport range and the `width` and `height` the container should use within that range. The placement only renders when at least one breakpoint matches the current viewport width. > If you define `breakpoints` and no entry matches the current viewport, the placement will not render at all. Make sure your breakpoints cover all the viewport widths you want the placement to appear on. - `breakpoints` (BreakpointConfig[]): Array of viewport-specific sizing rules. Each item can include the following fields: Minimum viewport width in pixels for this breakpoint to apply. Omit to match all widths up to `maxViewportWidth`. - `maxViewportWidth` (number): Maximum viewport width in pixels for this breakpoint to apply. Omit to match all widths from `minViewportWidth` upward. - `width` (string): Width of the placement container at this breakpoint. Accepts any valid CSS size value (e.g. `'100%'`, `'320px'`). - `height` (string): Height of the placement container at this breakpoint. Accepts any valid CSS size value (e.g. `'48px'`, `'auto'`). ```javascript // Placement only renders on viewports ≥768px at 48px tall, // or on viewports ≤767px at 40px tall. window.InlineAI.mount(window.InlineAI.Placement.SearchEmbed, { containerId: 'search-area', breakpoints: [ { minViewportWidth: 768, width: '100%', height: '48px' }, { maxViewportWidth: 767, width: '100%', height: '40px' }, ], }); ``` You can also use `minViewportWidth` and `maxViewportWidth` together to target a specific range: ```javascript // Only render on tablets (768px–1023px) window.InlineAI.mount(window.InlineAI.Placement.KeyTakeaways, { selector: '.article-sidebar', breakpoints: [ { minViewportWidth: 768, maxViewportWidth: 1023, width: '280px', height: 'auto' }, ], }); ``` ## Overlay breakpoints Overlay breakpoints are part of `MountOptions` (the third argument to `mount()`). They override the search overlay's type, backdrop opacity, and open trigger at specific viewport widths. You would typically use a modal on wider screens and a drawer on narrower ones. When multiple overlay breakpoints match the current viewport, the most specific one (the breakpoint with the narrowest defined range) wins. - `overlayBreakpoints` (OverlayBreakpointConfig[]): Array of viewport-specific overlay configuration overrides. Each item can include the following fields: Minimum viewport width in pixels for this breakpoint to apply. - `maxViewportWidth` (number): Maximum viewport width in pixels for this breakpoint to apply. - `overlayType` (string): Overlay type at this breakpoint. Accepts `'modal'` or `'drawer'`. - `backdropOpacity` (number): Backdrop opacity at this breakpoint. Accepts a value between `0` and `1`. - `openOverlayOn` (string): When to open the overlay at this breakpoint. Accepts `'onQuerySubmit'` or `'onFocus'`. ```javascript // Modal on desktop, drawer on mobile, with different open triggers too window.InlineAI.mount(window.InlineAI.Placement.SearchEmbed, 'search-container', { overlayBreakpoints: [ { minViewportWidth: 768, overlayType: 'modal', backdropOpacity: 0.6 }, { maxViewportWidth: 767, overlayType: 'drawer', openOverlayOn: 'onFocus' }, ], }); ``` ## Combining both breakpoint types You can use placement breakpoints and overlay breakpoints together on the same `mount()` call. They are evaluated independently. Placement breakpoints control whether and how large the container renders; overlay breakpoints control how the search results appear when the user interacts with it. ```javascript var { Placement, OverlayType, OpenOverlayOn } = window.InlineAI; window.InlineAI.mount(Placement.SearchEmbed, { containerId: 'search-area', breakpoints: [ { minViewportWidth: 768, width: '100%', height: '48px' }, { maxViewportWidth: 767, width: '100%', height: '40px' }, ], }, { overlayType: OverlayType.Modal, overlayBreakpoints: [ { minViewportWidth: 768, overlayType: OverlayType.Modal, backdropOpacity: 0.6 }, { maxViewportWidth: 767, overlayType: OverlayType.Drawer, openOverlayOn: OpenOverlayOn.Focus }, ], }); ``` > Define placement breakpoints in pairs that cover the full range of viewports you care about. Gaps between breakpoints mean the placement will not render in that range. --- # Events overview Source: https://docs.getinline.io/events/overview The Inline AI SDK emits events throughout its lifecycle: when it initializes, when a search overlay opens, when a placement mounts, and more. By subscribing to these events you can connect Inline AI to your own analytics pipeline, react to user interactions, synchronize UI state, or trigger custom behavior without polling or modifying SDK internals. ## Subscribing with `on()` Call `window.InlineAI.on(event, handler)` to register a listener. The method returns an **unsubscribe function**. Call it when you no longer need the listener. ```javascript var unsubscribe = window.InlineAI.on(window.InlineAI.Events.SearchOpen, function(data) { console.log('Search opened:', data.query); }); // Stop listening later unsubscribe(); ``` You can register as many handlers as you like for the same event, and each returns its own independent unsubscribe function. ## Unsubscribing with `off()` If you prefer to manage subscriptions by handler reference rather than capturing the return value, use `window.InlineAI.off(event, handler)`. You must pass the **same function reference** that was passed to `on()`. ```javascript var { Events } = window.InlineAI; function handleSearchOpen(data) { console.log('Search opened:', data.query); } window.InlineAI.on(Events.SearchOpen, handleSearchOpen); // Later: must use the same reference window.InlineAI.off(Events.SearchOpen, handleSearchOpen); ``` ## Using enum constants vs. raw strings Every event has both an enum constant on `window.InlineAI.Events` and a raw string value. Both forms work everywhere; choose whichever is clearer in your codebase. ```javascript // These are equivalent: window.InlineAI.on(window.InlineAI.Events.Ready, handler); window.InlineAI.on('ready', handler); ``` > Prefer the enum constants (`Events.Ready`, `Events.SearchOpen`, etc.) when writing code you'll maintain over time. They're less error-prone and make typos obvious at a glance. ## Using `on()` with the command queue If you need to subscribe before the SDK script has loaded, push an `'on'` command to the command queue. Commands are buffered and replayed in order once the SDK is ready. ```javascript window.InlineAI = window.InlineAI || {}; window.InlineAI.cmd = window.InlineAI.cmd || []; window.InlineAI.cmd.push(['on', window.InlineAI.Events.SearchOpen, function(data) { console.log('Search opened:', data.query); }]); ``` You can also use the callback form to access the SDK instance directly: ```javascript window.InlineAI.cmd.push(function(sdk) { sdk.on(sdk.Events.SearchOpen, function(data) { analytics.track('search_opened', { query: data.query }); }); }); ``` ## Practical use cases **Analytics tracking.** Send search queries and widget interactions to your analytics provider: ```javascript var { Events } = window.InlineAI; window.InlineAI.on(Events.SearchOpen, function(data) { analytics.track('inline_search_opened', { query: data.query }); }); window.InlineAI.on(Events.SearchClose, function(data) { analytics.track('inline_search_closed', { method: data.method }); }); window.InlineAI.on(Events.WidgetOpen, function() { analytics.track('inline_widget_opened'); }); ``` **UI integration.** Show or hide your own page elements in response to SDK state: ```javascript var { Events } = window.InlineAI; window.InlineAI.on(Events.SearchOpen, function() { document.getElementById('site-header').classList.add('search-active'); }); window.InlineAI.on(Events.SearchClose, function() { document.getElementById('site-header').classList.remove('search-active'); }); ``` **Lifecycle management.** Wait for the SDK or config to be ready before calling other methods: ```javascript var { Events } = window.InlineAI; window.InlineAI.on(Events.Ready, function() { // Safe to call mount() now window.InlineAI.mount(window.InlineAI.Placement.KeyTakeaways, 'sidebar'); }); window.InlineAI.on(Events.ConfigLoad, function() { console.log('Publisher config loaded; placements may now reflect dashboard settings'); }); ``` **Placement tracking.** Observe which placements are mounting and where: ```javascript var { Events } = window.InlineAI; window.InlineAI.on(Events.PlacementMount, function(info) { console.log('Mounted:', info.type, '(id:', info.id + ') in', info.container); }); window.InlineAI.on(Events.PlacementUnmount, function(info) { console.log('Unmounted:', info.type, '(id:', info.id + ')'); }); ``` ## Complete example The following snippet registers listeners for all event categories. Each handler is independent. Unsubscribe any one of them without affecting the others. ```javascript var { Events } = window.InlineAI; // Lifecycle window.InlineAI.on(Events.Ready, function() { console.log('SDK ready'); }); window.InlineAI.on(Events.ConfigLoad, function() { console.log('Config loaded'); }); // Search window.InlineAI.on(Events.SearchOpen, function(data) { console.log('User searched:', data.query); }); window.InlineAI.on(Events.SearchClose, function(data) { console.log('Search closed:', data.method); }); // Widget window.InlineAI.on(Events.WidgetOpen, function() { console.log('Widget opened'); }); window.InlineAI.on(Events.WidgetClose, function() { console.log('Widget closed'); }); // Placements window.InlineAI.on(Events.PlacementMount, function(info) { console.log('Mounted:', info.type, info.id); }); window.InlineAI.on(Events.PlacementUnmount, function(info) { console.log('Unmounted:', info.type, info.id); }); ``` > `Events.Ready` fires when the SDK is initialized and ready to accept `mount()` calls. Publisher page configuration may still be loading at that point. If your code depends on dashboard config being present, wait for `Events.ConfigLoad` instead. --- # Events reference Source: https://docs.getinline.io/events/reference This page documents every event the Inline AI SDK emits, grouped by category. For each event you'll find the enum constant, its raw string equivalent, a description of when it fires, the shape of the data it delivers to your handler, and a usage example. For a conceptual introduction to the event system (including how `on()` and `off()` work), see [Reacting to Inline AI events in your page](/events/overview). ## Subscribing and unsubscribing ### `on(event, handler)` → `unsubscribe` Registers a handler for the given event. Returns a function you can call to remove that specific listener. ```javascript // Using the return value to unsubscribe var unsubscribe = window.InlineAI.on(window.InlineAI.Events.SearchOpen, handler); unsubscribe(); // removes this listener only ``` | Parameter | Type | Description | |-----------|------|-------------| | `event` | `SDKEventName` or `Events.*` | The event to subscribe to | | `handler` | `function` | Called each time the event fires, receives the event payload | **Returns:** A zero-argument function that removes this listener when called. ### `off(event, handler)` Removes a specific handler by reference. You must pass the **same function reference** that was originally passed to `on()`. ```javascript function handler(data) { console.log(data); } window.InlineAI.on(window.InlineAI.Events.SearchOpen, handler); // Later: must be the same reference window.InlineAI.off(window.InlineAI.Events.SearchOpen, handler); ``` | Parameter | Type | Description | |-----------|------|-------------| | `event` | `SDKEventName` or `Events.*` | The event to unsubscribe from | | `handler` | `function` | The exact function reference passed to `on()` | > Anonymous functions cannot be removed with `off()` because each function literal creates a new reference. Use a named function or capture the unsubscribe return value from `on()` instead. --- ## Lifecycle events Lifecycle events tell you when the SDK is initialized and when publisher configuration has finished loading from the API. #### Events.Ready: SDK initialized **Enum constant:** `Events.Ready` **Raw string:** `'ready'` Fires once the SDK has initialized and is ready to accept `mount()` calls. Publisher page configuration from the dashboard may still be loading at this point. If your code depends on it, wait for `Events.ConfigLoad` instead. **Payload:** none ```javascript window.InlineAI.on(window.InlineAI.Events.Ready, function() { // Safe to call mount() here window.InlineAI.mount(window.InlineAI.Placement.KeyTakeaways, 'sidebar'); }); ``` #### Events.ConfigLoad: publisher config loaded **Enum constant:** `Events.ConfigLoad` **Raw string:** `'config:loaded'` Fires when the publisher page configuration has fully loaded from the Inline AI API. Use this event when your code depends on dashboard settings being available before proceeding. **Payload:** none ```javascript window.InlineAI.on(window.InlineAI.Events.ConfigLoad, function() { console.log('Publisher configuration is ready'); }); ``` --- ## Placement events Placement events fire each time a placement is added to or removed from the page, whether by auto mode, programmatic `mount()` calls, or `unmount()`. #### Events.PlacementMount: placement mounted **Enum constant:** `Events.PlacementMount` **Raw string:** `'placement:mounted'` Fires after a placement has been successfully mounted into the DOM. **Payload:** | Field | Type | Description | |-------|------|-------------| | `id` | `string` | The placement ID (pass to `unmount()` to remove it) | | `type` | `string` | The placement type, e.g. `'search-embed'`, `'widget'` | | `container` | `HTMLElement` | The DOM element hosting the placement | ```javascript window.InlineAI.on(window.InlineAI.Events.PlacementMount, function(info) { console.log('Mounted:', info.type, 'id:', info.id); console.log('Container element:', info.container); }); ``` #### Events.PlacementUnmount: placement unmounted **Enum constant:** `Events.PlacementUnmount` **Raw string:** `'placement:unmounted'` Fires after a placement has been removed from the DOM, either via `unmount()` or `destroy()`. **Payload:** | Field | Type | Description | |-------|------|-------------| | `id` | `string` | The placement ID that was removed | | `type` | `string` | The placement type that was removed | ```javascript window.InlineAI.on(window.InlineAI.Events.PlacementUnmount, function(info) { console.log('Unmounted:', info.type, 'id:', info.id); }); ``` --- ## Search events Search events fire when the search overlay opens or closes. Use them to track search activity or synchronize your own UI. #### Events.SearchOpen: search overlay opened **Enum constant:** `Events.SearchOpen` **Raw string:** `'search:open'` Fires when the search overlay opens, whether triggered by a user interaction or a programmatic `open()` call. **Payload:** | Field | Type | Description | |-------|------|-------------| | `query` | `string` | The search query string at the time the overlay opened (may be empty) | ```javascript window.InlineAI.on(window.InlineAI.Events.SearchOpen, function(data) { // Send to your analytics provider analytics.track('search_opened', { query: data.query }); }); ``` #### Events.SearchClose: search overlay closed **Enum constant:** `Events.SearchClose` **Raw string:** `'search:close'` Fires when the search overlay closes, whether the user dismissed it or it was closed programmatically. **Payload:** | Field | Type | Description | |-------|------|-------------| | `method` | `string` | How the overlay was closed (e.g. user interaction or programmatic call) | ```javascript window.InlineAI.on(window.InlineAI.Events.SearchClose, function(data) { console.log('Search closed via:', data.method); }); ``` --- ## Widget events Widget events fire when the sticky Widget panel opens or closes. #### Events.WidgetOpen: widget panel opened **Enum constant:** `Events.WidgetOpen` **Raw string:** `'widget:open'` Fires when the sticky widget panel opens. **Payload:** none ```javascript window.InlineAI.on(window.InlineAI.Events.WidgetOpen, function() { analytics.track('widget_opened'); }); ``` #### Events.WidgetClose: widget panel closed **Enum constant:** `Events.WidgetClose` **Raw string:** `'widget:close'` Fires when the sticky widget panel closes. **Payload:** none ```javascript window.InlineAI.on(window.InlineAI.Events.WidgetClose, function() { analytics.track('widget_closed'); }); ``` --- ## All events at a glance | Enum constant | Raw string | Payload | When it fires | |---------------|-----------|---------|---------------| | `Events.Ready` | `'ready'` | none | SDK initialized; ready for `mount()` calls | | `Events.ConfigLoad` | `'config:loaded'` | none | Publisher page config loaded from API | | `Events.PlacementMount` | `'placement:mounted'` | `{ id, type, container }` | A placement was added to the DOM | | `Events.PlacementUnmount` | `'placement:unmounted'` | `{ id, type }` | A placement was removed from the DOM | | `Events.SearchOpen` | `'search:open'` | `{ query }` | Search overlay opened | | `Events.SearchClose` | `'search:close'` | `{ method }` | Search overlay closed | | `Events.WidgetOpen` | `'widget:open'` | none | Sticky widget panel opened | | `Events.WidgetClose` | `'widget:close'` | none | Sticky widget panel closed | --- ## TypeScript type reference If you're using TypeScript, the `SDKEventName` union type covers all valid event name strings: ```typescript type SDKEventName = | "ready" | "config:loaded" | "placement:mounted" | "placement:unmounted" | "search:open" | "search:close" | "widget:open" | "widget:close"; ``` --- # Programmatic control Source: https://docs.getinline.io/guides/programmatic-control Auto mode handles placement rendering for most sites, but some scenarios require direct control: single-page apps that need to mount and unmount placements as routes change, custom UI triggers that open search from your own buttons, or dynamic content pages where the right moment to render a placement depends on runtime conditions. This guide covers the full programmatic API for controlling what renders, when it renders, and how it opens. ## When to use programmatic control - Single-page apps: Mount placements after route changes and unmount them before navigating away to avoid stale placements. - Custom search triggers: Open the search overlay from your own nav bar, keyboard shortcut, or CTA button. - Dynamic content: Mount placements only after your content has loaded or a user has reached a certain scroll depth. - Full lifecycle control: Use `destroy()` and `init()` to completely reset the SDK between page transitions. ## Initializing in programmatic mode In programmatic mode, the SDK does not auto-render placements from your dashboard config. You call `init()` explicitly, then mount each placement you want. ```js // Set up the queue before the script tag window.InlineAI = window.InlineAI || {}; window.InlineAI.cmd = window.InlineAI.cmd || []; window.InlineAI.cmd.push(['init', { publisherId: 'YOUR_PUBLISHER_ID' }]); ``` > Calling `init()` before the SDK loads (either via the command queue or inline) activates programmatic mode. The SDK will not render anything automatically until you call `mount()`. ## Mounting placements ### Mounting on the ready event The `Events.Ready` event fires once the SDK is initialized and accepting `mount()` calls. This is the right place to mount your initial set of placements. ```js window.InlineAI.on(window.InlineAI.Events.Ready, function() { window.InlineAI.mount(window.InlineAI.Placement.SearchEmbed, 'search-box'); window.InlineAI.mount(window.InlineAI.Placement.Widget); }); ``` ### Mounting by element ID Pass a string to mount a placement into a specific element by its `id` attribute. ```js // Mounts into var id = window.InlineAI.mount(window.InlineAI.Placement.KeyTakeaways, 'sidebar'); ``` `mount()` returns a placement ID string. Save it if you need to unmount the placement later. ### Body-level placements `Placement.SearchFab` and `Placement.Widget` attach to the page body and do not require a target element. ```js window.InlineAI.mount(window.InlineAI.Placement.SearchFab); window.InlineAI.mount(window.InlineAI.Placement.Widget); ``` ## Unmounting placements Call `unmount()` with the ID returned by `mount()` to remove a placement from the page. ```js var id = window.InlineAI.mount(window.InlineAI.Placement.BasicEmbed, 'sidebar'); // Later, e.g. before a route change in an SPA window.InlineAI.unmount(id); ``` > After calling `unmount()`, the placement ID is no longer valid. If you need the placement again, call `mount()` to get a new ID. ## Inspecting mounted placements `getPlacements()` returns an array of all currently mounted placements. Each object contains the placement ID, type, and the DOM container element. ```js var placements = window.InlineAI.getPlacements(); placements.forEach(function(p) { console.log(p.id, p.type, p.container); }); ``` | Field | Type | Description | |---|---|---| | `id` | `string` | Placement ID, usable with `unmount()` | | `type` | `string` | Placement type (e.g. `'search-embed'`) | | `container` | `HTMLElement` | The DOM element hosting the placement | > `getPlacements()` is not available through the command queue before the SDK loads. Call it only after the `Events.Ready` event has fired. ## Opening overlays programmatically ### Open search with a pre-filled query You can open the search overlay from any event handler and optionally pre-fill a query string. This is useful for "search for this" links or contextual CTAs. ```js document.getElementById('my-search-btn').addEventListener('click', function() { window.InlineAI.open(window.InlineAI.OverlayTarget.Search, 'How do I get started?'); }); ``` Omit the query argument to open search with an empty input. ```js window.InlineAI.open(window.InlineAI.OverlayTarget.Search); ``` ### Open and close the widget By default, opening the widget with `open(OverlayTarget.Widget)` **auto-answers** the current catalog question when one is available — same behavior as the user tapping **See Answer** on the FAB notification. To open the panel only without starting a stream, pass `{ autoAnswer: false }`. ```js // Open the sticky widget panel (auto-answer when a catalog question is pending) window.InlineAI.open(window.InlineAI.OverlayTarget.Widget); // Open only — user interacts with suggested questions manually window.InlineAI.open(window.InlineAI.OverlayTarget.Widget, { autoAnswer: false }); // Close it programmatically window.InlineAI.close(window.InlineAI.OverlayTarget.Widget); ``` ### Open search with auto-answer The same `autoAnswer` option works for the search overlay. By default, `open(OverlayTarget.Search)` picks the next pending catalog question and auto-submits it. Pass an explicit `{ query }` to submit a specific question instead, or `{ autoAnswer: false }` to open the overlay empty. ```js // Auto-answer: opens search and submits the next catalog question window.InlineAI.open(window.InlineAI.OverlayTarget.Search); // Submit a specific question window.InlineAI.open(window.InlineAI.OverlayTarget.Search, { query: 'How do I get started?' }); // Open empty — let the user type window.InlineAI.open(window.InlineAI.OverlayTarget.Search, { autoAnswer: false }); ``` ### Close search ```js window.InlineAI.close(window.InlineAI.OverlayTarget.Search); ``` ## SPA route change pattern When navigating between routes in a single-page app, unmount the current placements, then mount the ones appropriate for the new route. ```js // On route change (pseudo-code; adapt to your router) function onRouteChange(newRoute) { // Remove all current placements var current = window.InlineAI.getPlacements(); current.forEach(function(p) { window.InlineAI.unmount(p.id); }); // Mount placements for the new route if (newRoute === '/articles') { window.InlineAI.mount(window.InlineAI.Placement.KeyTakeaways, 'article-sidebar'); window.InlineAI.mount(window.InlineAI.Placement.SearchFab); } else if (newRoute === '/') { window.InlineAI.mount(window.InlineAI.Placement.SearchEmbed, 'hero-search'); } } ``` ## Teardown and re-initialization `destroy()` removes all placements and tears down the SDK completely. You can bring it back up with `init()`. ```js // Full teardown window.InlineAI.destroy(); // Re-initialize (e.g., after switching publisher context) window.InlineAI.init({ publisherId: 'YOUR_PUBLISHER_ID' }); ``` > Use `destroy()` followed by `init()` when you need to switch publisher IDs at runtime, or when a full reset is cleaner than individually unmounting every placement. --- # Command queue Source: https://docs.getinline.io/guides/command-queue The Inline AI script loads asynchronously, which means your JavaScript may run before the SDK is available on the page. The command queue solves this: it lets you call SDK methods immediately, buffering them until the SDK is ready to execute them in order. Once the script has loaded, any further calls to `cmd.push()` run right away. This guide explains how the queue works, which syntax to use, and how to structure your setup code correctly. ## How the command queue works When you add the queue setup snippet before the script tag, you create a plain JavaScript array at `window.InlineAI.cmd`. Your calls to `cmd.push()` add entries to that array. When the Inline AI script loads, it reads every entry in the array, executes them in sequence, and then replaces `cmd` with a live dispatcher, so any subsequent `cmd.push()` calls execute immediately. This pattern is intentionally simple: no special libraries, no build tools, no dependencies. It works in any browser that supports a basic ` ``` ## Mixing array and callback syntax You can freely mix both syntaxes in the same queue. Commands execute in the order they are pushed, regardless of which syntax was used. ```js // Array syntax for simple calls window.InlineAI.cmd.push(['init', { publisherId: 'YOUR_PUBLISHER_ID' }]); window.InlineAI.cmd.push(['mount', window.InlineAI.Placement.Widget]); // Callback syntax where you need the placement ID window.InlineAI.cmd.push(function(sdk) { var searchId = sdk.mount(sdk.Placement.SearchEmbed, 'search-area'); sdk.on(sdk.Events.PlacementMount, function(info) { if (info.id === searchId) { console.log('Search embed is live'); } }); }); ``` ## Best practices #### Always set up the queue before the script tag If the Inline AI script loads before your queue initialization code runs, commands pushed before load will not be buffered. Put the queue setup and all your `cmd.push()` calls in a `