HomeBook a Demo

Single question

Distribute AI-generated in-content question pills across your article's paragraphs to drive engagement and surface related queries inline.

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.

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, and the target must be the element that contains your article text. Unlike the other embed placements, the SDK does not render into the target: it scans inside it for anchor elements and inserts each pill container as a sibling of one. Point it at an empty placeholder, such as an ad-slot div you added for the purpose, and it finds no anchors and the mount fails. Target the element that directly wraps your article body text.

Mounting from the command queue

To mount from your page markup rather than after the script has loaded, push the command onto the command queue. Entries are buffered and replayed in order once the SDK is ready.

<script>
  window.InlineAI = window.InlineAI || {};
  window.InlineAI.cmd = window.InlineAI.cmd || [];
 
  // init() activates programmatic mode
  window.InlineAI.cmd.push(['init', { publisherId: 'YOUR_PUBLISHER_ID' }]);
 
  window.InlineAI.cmd.push(['mount', 'single-question', {
    dynamic: { tagName: 'article' },
    injectionLimit: 3,
    injectionStrategy: 'distribute-evenly',
  }]);
</script>

Place that block before the embed snippet.

Pass the string values here ('single-question', 'distribute-evenly') rather than window.InlineAI.Placement.SingleQuestion and window.InlineAI.InjectionStrategy.DistributeEvenly. The enums are installed by the script itself, so they are not available to code that runs before it. See enums and the command queue.

Targeting the container

window.InlineAI.mount(window.InlineAI.Placement.SingleQuestion, {
  dynamic: { tagName: 'article' },
  injectionLimit: 3,
  injectionStrategy: window.InlineAI.InjectionStrategy.DistributeEvenly,
});

How anchors are selected

The SDK collects the anchor elements inside the target, discards the ones that do not qualify, then picks up to injectionLimit of them and inserts a pill container next to each.

  • The default anchor is <p>. Override it with anchorInjection when your body copy is not made of paragraphs.
  • An anchor only qualifies if its text is at least 100 characters long. Captions, bylines, and one-line paragraphs are skipped.
  • injectionSelectorOffset is applied before the length filter, so it counts every matching anchor in the target, not just the qualifying ones.

If nothing qualifies, no pills are injected and the mount fails.

Injecting into a fixed slot

To render one pill in a slot you control, rather than distributing pills through the article, point anchorInjection at the slot and use the manual strategy.

location defaults to 'below', which inserts the pill container after your slot as a sibling, not inside it. Use 'append' or 'prepend' to render inside the slot.

window.InlineAI.cmd.push(['mount', 'single-question', {
  selector: 'body',
  anchorInjection: { tagName: 'div', attributeName: 'id', attributeValue: 'my-slot' },
  injectionStrategy: 'manual',
  injectionLimit: 1,
  location: 'append',
}]);

The slot can be empty. Manual assigns questions to anchors sequentially in document order and skips the content matching the other strategies do, so there is no surrounding text it needs to match against.

mount() de-duplicates on the pair of placement type and resolved target element. Two single question mounts that both resolve selector: 'body' share a target, so the second logs a warning, returns the first placement's ID, and injects nothing. To fill several slots, use one mount whose anchorInjection matches all of them, for example a shared class, and raise injectionLimit to the number of slots.

When nothing renders

mount() does not throw. On failure it returns undefined and logs the reason to the browser console, so open the console first.

An empty or paragraph-less target logs:

[inline-tech] [SDK] mount(): Error: mount('single-question'): no qualifying anchor elements found in target element. Anchor elements must be at least 100 characters long.

A target that does not exist yet logs:

[inline-tech] [SDK] mount(): Error: mount('single-question'): element with id 'article-body' not found

The target is resolved once, at mount time. When you mount from the command queue, the element must already be in the DOM by the time the SDK script loads and replays the queue. Queued mounts are not retried against DOM that arrives later.

Injection options

injectionLimitQuerynumber

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.

injectionStrategyQueryInjectionStrategy

How to distribute pills across the content:

  • window.InlineAI.InjectionStrategy.Default ("default"): walks the qualifying anchors from the top and takes the first one, then keeps a gap of at least 4 anchors between pills.
  • window.InlineAI.InjectionStrategy.DistributeEvenly ("distribute-evenly"): spaces pills evenly across the qualifying anchors.
  • window.InlineAI.InjectionStrategy.Manual ("manual"): takes the matching anchors in document order and skips the 100-character text filter. Pair it with anchorInjection when you have selected the anchors yourself.
injectionSelectorOffsetQuerynumber

Offset for the first injection point. A value of 1 skips the first paragraph and starts injecting from the second.

anchorInjectionQueryobject

Which element inside the target is used as the injection anchor. Defaults to <p>. Set it when your body content is not made of paragraphs, for example forum answers rendered as div or list items.

typographySourceQueryTypographySource

Typography inheritance mode for the question pills: "inherit-from-website" or "inherit-from-theme".

Sizing and positioning

locationQueryInjectionLocation

Where to inject each pill relative to its anchor element. Defaults to "below".

  • "prepend" and "append" render inside the anchor, as its first or last child.
  • "above" and "below" render outside it, as a sibling before or after.
widthQuerystring

Width of each pill container as a CSS value.

maxWidthQuerystring

Maximum width of each pill container.

breakpointsQueryBreakpointConfig[]

Responsive breakpoints for controlling when and at what size pills render.

Examples

window.InlineAI.mount(window.InlineAI.Placement.SingleQuestion, {
  dynamic: { tagName: 'article' },
  injectionLimit: 3,
  injectionStrategy: window.InlineAI.InjectionStrategy.DistributeEvenly,
});

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 and SPA routing patterns, see the programmatic control guide.