iAdvizeDocs
Engagement widgets

Place an inline button on your pages

The three ways to tell the tag where an inline button goes, ranked best first: what the custom element buys you, and what the CSS selector costs.

An inline button has no docked corner. Its position is a point inside your own page, and you decide where that point is. The Display tab of the widget editor asks how the tag should find it, and offers three modes.

The same mount modes place Starters

Everything on this page (the three modes, the ranking, the four-second watch window and the mount check) applies unchanged to Starters, the composite heading-plus-chips-plus-field widget. The two formats share one mount mechanism; only what gets placed at the mount point differs.

They are not three equivalent options. They are one ranked recommendation, best first. The same ranking, in the same words, the editor shows you at the moment you choose:

RankYou addAppears with no waitingSurvives a theme changeSpace can be reserved
1. Custom element (recommended)<iadvize-widget data-iadvize-slot="…"> in your templateYesYesYes
2. Marker elementdata-iadvize-slot="…" on an element you already haveNoYesYes
3. CSS selectorNothing: you configure the selector in the dashboardNoNoNo

A new inline widget arrives with mode 3 already selected, and that is deliberate: nobody should be blocked from configuring and publishing a widget while they wait on someone else to edit a template. Going through an integrator, an internal front-end team or a web agency is the ordinary situation, not a failure, and mode 3 is what lets you ship today.

It is also the only mode that can break without telling you. Both things are true at once, which is why the ranking is shown rather than implied: pick mode 3 knowing what it costs, and pick mode 1 if you can reach a template.

Put our element where the button should go:

your-product-template.html
<iadvize-widget data-iadvize-slot="product-cta"></iadvize-widget>

Then set the widget's mode to Our element in your template and enter the same slot name.

Three reasons it is the one we recommend:

  • It appears as soon as your page renders it. The browser hands us the element the moment it enters the document, whether it was in the HTML you served, or inserted later by a client-side re-render, or removed and put back. There is no window to miss and nothing to scan for, so the button cannot fail to appear because a target arrived late or a re-render replaced it. (No widget of any format renders before the tag has fetched your site's configuration; an element already in your HTML is held and mounted as soon as it has.)
  • It survives a theme change. The mount point lives in your template, next to the thing it belongs beside. Nothing about it depends on a class name that front-end work can rename.
  • You can reserve its space, which is the only way to get the button with no layout shift at all.

Two copies of our install snippet on one page don't break it either: registering the element twice would normally throw, and we guard for it.

Reserve the space

An element the browser has never heard of is laid out as display: inline and has no box of its own, so a min-height alone does nothing until you also give it a box:

your-storefront.css
iadvize-widget[data-iadvize-slot='product-cta'] {
  display: block;
  min-height: 56px;
}

Match the height to the widget's Size on its Design tab: 48 px (Small), 56 px (Medium, the default for a button) or 64 px (Large). With the box already that tall, nothing on the page moves when the button lands in it.

Height is the dimension that matters, because that is what the button adds to a normal block flow. We deliberately don't hand you a full reserved box: the button's width follows its label, which is per-language and rendered in your own font, so we cannot compute it for you. If your mount point sits in a row where the button's width would move its neighbours, reserve a width too.

Never use the bare `slot` attribute

The attribute is data-iadvize-slot, in both element modes. slot on its own is a global HTML attribute the browser acts on: it assigns the element to a named slot in an enclosing shadow host, and where no matching <slot name> exists the element is not rendered at all. If your storefront is built with a component library, our element will sooner or later sit inside one of your own web components, and with the bare attribute it would silently render nothing there.

2. Marker element

Add the same attribute to an element you already have, or to an empty one you add for the purpose:

your-product-template.html
<div data-iadvize-slot="product-cta" style="min-height: 56px"></div>

Then set the widget's mode to Your element, marked for us.

The button is appended inside the marked element, as its last child. If the element already has content, the button lands after it.

This keeps two of the three advantages above (it survives a theme change, and you can reserve its height on your own element) and loses the first: we have to find the marked element by looking for it, under the bounded window below.

3. CSS selector: the one the editor pre-selects

Name an element with a CSS selector and say where to put the button relative to it. Nothing changes in your code.

Two costs, and they are the point of this section rather than a note at the bottom:

  • Content below the button moves down when it appears. The container isn't ours, so there is no space to reserve. On our own test page the merchant content below an unreserved mount point moved by 72 px, scoring a 0.0325 layout shift. Your own figure depends on your type scale; the direction doesn't.
  • A theme change can rename the target, and the button silently stops appearing. Nothing is broken on the page, nothing errors, and your dashboard still reports the widget as live. Front-end work that renames .product-form__buttons is enough.

And the one thing only this mode offers, which is a real advantage: nobody else has to be involved. You configure it and publish it yourself.

Where the button goes relative to the target

Editor labelWhere it lands
Just before itImmediately before the element
Just after itImmediately after it (the default)
Inside, firstAs the element's first child
Inside, lastAs the element's last child

There is deliberately no "replace". It would make us responsible for removing content we don't own and can't put back: a selector written slightly too broadly would erase part of a product page instead of merely failing to place a button, and nothing in the page could undo it.

Every match gets a button

If your selector matches four elements, four buttons are placed, not one.

That is on purpose. E-commerce themes routinely ship the same block twice, once for desktop and once for mobile, with one of the two hidden by CSS. Placing only the first would put the button in whichever copy comes first in the document and make it vanish on the other: usually the mobile one, which is where most of your traffic is.

The consequence is the obvious one: a broad selector places several buttons. The mount check tells you how many matched, so you can see it before publishing rather than after.

Slot names

The two element modes identify the mount point by a slot name you choose. It is free text, with rules:

  • lowercase letters, digits and dashes only;
  • it must start with a letter or a digit;
  • up to 64 characters.

The editor suggests product-cta, product-price, plp-header and cart-summary as one-click starting points, and doesn't restrict you to them.

A slot names a position, not a widget, so you can change which widget occupies that position later without touching your template, and duplicating a widget doesn't orphan the markup you wrote.

Two live widgets on one site cannot share a slot. The editor warns you as soon as you type a slot name a live widget already holds, and names that widget. If you publish anyway, the publish is refused (by the database, with a generic "Could not save your changes"), which is exactly why the earlier warning is worth reading. A draft may share a live widget's slot; only publishing is refused. Different sites, and different organizations, can each use product-cta freely.

The check is on the slot name, not on the selector

Two widgets pointed at the same CSS selector are not refused, and the overlap warning can't see it either: that warning reasons about corners of the viewport, which an inline widget doesn't have. Two buttons on one spot is your call to avoid.

How long we look for a target

This section applies to modes 2 and 3 only. The custom element needs none of it.

The tag looks for a matching element as soon as it has loaded the site's configuration, and keeps watching your document for one that isn't there yet, for about four seconds, then it stops. An observer left running on a merchant's page is a cost nobody can see, so it is bounded.

Three things follow:

  • A target rendered a little late is still found. A theme that renders its add-to-cart block after the initial paint is well inside the window.
  • A target replaced during the window is followed. If your page re-renders the block the button is in (a variant switch through the Shopify sections API, a listing filter, anything that swaps markup in place without changing the URL), the button is placed again in the replacement. This is the case the watch stays open for, so it does not stop at the first success.
  • After the window closes, we stop. A re-render that replaces the target more than about four seconds in leaves the button gone until the next navigation or reload.

A change to the page's path or query string re-arms the watch, which covers a re-render whose new markup arrives a moment after the URL changes. The same element is never given two buttons, however many times we re-scan.

An inline widget needs page types

An inline widget (a button or a Starters widget) renders only on a page whose type your storefront has declared, and only if that type is one you checked.

  • Your page must call iadvize('set', { customData: { pageType: … } }). A page that declares nothing gets no inline widget, even if it's live and its target is right there.
  • Show on all pages is not offered for an inline format. Its position only exists on the pages that have it, so "everywhere" has no meaning.

A new button or Starters widget arrives with all four page types already checked (the closest to "everywhere" an inline format supports), so you'll usually be narrowing this down rather than starting from nothing. It still won't render on a page that declares no type at all, whatever you have checked.

This is stricter than a chat bubble or question bar, which still show on a page that declares no type. Combined with placing every match, a broad selector on an undeclared page would put a button (or a whole Starters card) across a listing, so the rule is inverted for inline formats specifically.

If you switch an existing widget to an inline format while Show on all pages was on, the mode is dropped along with the other settings the new format has no place for (the format-change dialog lists it), and the widget falls back to the page types you have checked. Pick at least one and it goes live.

Check it before you publish

The Display tab carries a mount check that reports what the tag actually found on a real page of yours.

Save a draft, then use Preview link in the action bar to mint a storefront preview link for this widget. The check rides on that link's token.

Switch the preview column to Real site and point the URL at the page you're targeting: a product page, not the home page.

Read the verdict: Found on this page, Found N times on this page, or Not found on this page. Checking… means nothing has been reported yet, which is not the same as not found.

For an inline widget, the framed page is loaded with your tag active and this widget's draft previewed, so the button appears where it really lands, rather than being drawn by the dashboard in a position it cannot know. Without an outstanding preview link the frame loads with the tag disabled instead: you see your page, no button, and no verdict.

Three things the panel says out loud, because each is a way the verdict gets misread:

  • Its scope. It covers the page you previewed, at the moment you previewed it, not your site. Pages you didn't preview are not covered.
  • What the widget targets. The panel lists the widget's page types beside the verdict. A selector that is correct on the home page and wrong on the product template is the typical failure.
  • It does not block publishing. A not-found verdict changes nothing about the widget's status, and publishing anyway is a legitimate order of work: you configure and publish, your integrator places the element afterwards.

The match count deliberately ignores page-type targeting. "Your selector matches nothing here" and "this widget doesn't target this page type" are different answers, and the panel gives you both.

When the mount doesn't resolve

Nothing renders. There is no fallback position, no second guess at a selector, and no "looks like an add-to-cart button" detection. A mount point we can't find means no widget, full stop.

Nothing appears on the page to say so either. We do record the failure on our side, but there is no report for it in your dashboard today, so the mount check above is what you have. When a button or a Starters widget doesn't show up, work through this:

  1. Does the page declare its page type, and is that type checked on the widget?
  2. Is the widget Active, and has the draft been published?
  3. In selector mode: does the selector still match? Paste it into document.querySelectorAll() in your browser console on the real page.
  4. In an element mode: is the attribute data-iadvize-slot (not slot), and does the name match the widget's slot exactly?
  5. Does it have text for the shopper's language, or for your site's default: the button's label, or Starters' heading? Either one renders nothing without it.
  6. Is the tag itself running on that page? If it isn't, no widget of any format appears.

Styling the button, and Starters

An inline button reuses the chat bubble's CSS contract (the same custom properties and the same shadow parts), with a host selector that depends on the mount mode. Starters shares the same host selectors and mount-mode logic, and reuses most of the same custom properties and parts for its own regions. See Style engagement widgets with CSS.

On this page