Inline Banners — Shopify Metafield Spec for Merchants
Schema reference for merchants who want to author collection-page inline banners that Marqo's storefront search widget will render automatically.
Audience: SEs and merchant marketing teams. No Marqo-side code change is required for any option — the widget reads these metafields on every collection page load.
Widget source: components/shopify/storefront_search/src/storefront.ts —
functions fetchCollectionPromotionalCards() and parseInlineBannerMetaobject().
Recommendation: Option D — custom.inline_banners
Use a list of metaobject references on the collection. Supports multiple banners per collection, separate desktop + mobile positioning, per-banner color and alignment overrides. The other options are kept for legacy reasons; D is what we'd build for any new merchant today.
Step 1 — Create the metaobject definition
In Shopify Admin → Settings → Custom data → Metaobjects → Add definition.
| Field | Value |
|---|---|
| Name | PLP Inline Banner |
| Handle | plp_inline_banner |
Fields:
| Field key | Type | Required | Notes |
|---|---|---|---|
title | Single line text | yes | Heading |
text | Rich text | no | Subcopy paragraph |
url | URL (or single-line text) | yes | Click target (desktop) |
url_mobile | URL | no | Click target on mobile (falls back to url) |
button_text | Single line text | no | CTA label |
button_style | Single line text | no | primary / secondary / etc. |
background_image | File (Image) | yes | Desktop banner image |
background_image_mobile | File (Image) | no | Mobile image (falls back to desktop) |
title_color | Single line text (hex) | no | e.g. #000000 |
text_color | Single line text (hex) | no | |
alignment | Single line text | no | left / center / right |
alignment_mobile | Single line text | no | |
location | Integer | yes | 1-based grid position (desktop), e.g. 6 or 10 |
location_mobile | Integer | no | 1-based grid position (mobile) |
Step 2 — Create banner entries
Shopify Admin → Content → Metaobjects → PLP Inline Banner → Add entry. Each entry is one banner. Authored once, reusable on any collection.
Step 3 — Attach banners to a collection
For each collection that should show banners, define a metafield on the Collection resource:
- Namespace and key:
custom.inline_banners - Type:
list.metaobject_referencereferencing theplp_inline_bannerdefinition created in step 1
Then edit the collection and set custom.inline_banners to a list of
references to the metaobject entries from step 2.
What the widget does automatically
On every collection page load:
- Reads
custom.inline_banners.referenceson the collection - For each referenced metaobject, renders a card at the configured
locationin the product grid - Uses
background_image_mobile+location_mobileif on mobile, else falls back to desktop values - Sanitizes any HTML, strips inline event handlers,
javascript:/data:URIs, and<script>/<iframe>tags
No Marqo settings push, no widget code change, no theme integration. The plumbing is already deployed.
Other supported options (legacy, not recommended for new merchants)
Option A — global.inline_banner (single metaobject reference)
Same plp_inline_banner metaobject schema as D, but the collection metafield
type is metaobject_reference (single reference, namespace global, key
inline_banner). One banner per collection only.
Option B — promotional_image.* (flat collection metafields)
Direct collection metafields, no metaobject indirection. Schema:
| Namespace | Key | Type |
|---|---|---|
promotional_image | title | rich_text |
promotional_image | subcopy | rich_text |
promotional_image | image | file (image) |
promotional_image | url | url |
promotional_image | button_text | single_line |
promotional_image | location | integer |
promotional_image | bg_color | single_line |
promotional_image | title_color | single_line |
promotional_image | subcopy_color | single_line |
promotional_image | button_style | single_line |
promotional_image | alignment | single_line |
promotional_image | switch_title_and_subtitle | boolean |
One banner per collection, no mobile-specific positioning.
Option C — promotional_image_2.*
Identical schema to B, parallel "second slot" namespace. Allows two banners per collection when combined with B. Still no mobile-specific positioning.
Comparison
| Option | Namespace | Multi-banner per collection? | Mobile position? | Reuse across collections? |
|---|---|---|---|---|
| D | custom.inline_banners (list of metaobjects) | unlimited | yes | yes |
| A | global.inline_banner (single metaobject) | 1 | yes | partial (single reference) |
| B | promotional_image.* (flat) | 1 | no | no |
| C | promotional_image_2.* (flat) | 1 (paired with B for total 2) | no | no |
Why D wins:
- Multiple banners per collection without merchant theme code change
- Reusable — author once, reference on many collections
- Mobile-specific positioning + image built in
- Cleaner merchant workflow — metaobjects have a dedicated editor under Shopify Admin → Content; flat metafields are scattered across each collection's individual settings
Coexistence with Marqo's static admin-configured banner path
Marqo also exposes a static, admin-configured banner path via the
grid_injections.items[] Marqo UI setting (Marqo admin UI, not Shopify
metafields). Both paths run additively — the widget reads both and renders
them in the same product grid. There is no mode toggle; if items[] is empty
(default), only metafield-driven banners render. If a merchant wants a mix of
admin-authored and Shopify-authored banners, both work simultaneously.
Verification — confirm metafields are exposed
Once a merchant has set up the metaobject definition and referenced at least one entry on a test collection, an SE can verify the data is queryable via the Shopify Storefront API:
curl -X POST \
-H "X-Shopify-Storefront-Access-Token: <storefront-api-token>" \
-H "Content-Type: application/json" \
-d '{
"query": "{ collectionByHandle(handle: \"<test-collection-handle>\") { metafield(namespace: \"custom\", key: \"inline_banners\") { references(first: 5) { nodes { ... on Metaobject { handle title: field(key: \"title\") { value } location: field(key: \"location\") { value } } } } } } }"
}' \
https://<shop>.myshopify.com/api/2025-01/graphql.json
Expected response: references.nodes array with metaobjects matching the
entries. Once that returns data, banners render on the next collection page
load on the merchant's Marqo-themed previews — no additional Marqo action
required.
Notes for SEs
- Marqo's storefront search widget reads these metafields from the Shopify Storefront API (not Admin API) at page-load time on each PLP. Make sure the metafields are exposed to the Storefront API ("Storefront access" toggled on in the metafield definition or storefront API permissions).
- Same metaobject can be referenced from multiple collections, mirroring global campaign behavior.
- For mobile parity, always populate
location_mobile— many merchants only set the desktop position and end up with banner positioning that breaks at small viewports. - If a merchant is migrating from a non-Marqo search platform with native PLP banners (e.g. Searchspring), this is the bridge to keep banner content unchanged from the customer's perspective.