Enable the Cinch headless core app embed. It loads the engine that recognizes these attributes. The standard Cinch bundle app blocks already load their own renderer and do not need this embed.
Published data
Each successful publish mirrors display-safe data into the public Shopify metafield namespace shop.metafields.cinch. The shop-level sf_indexlists campaign IDs, placement hints, and the merchant-configured metafield sources used by compatible collection-backed cards. Each campaign config lives atsfc_<campaignId>.
The display config and checkout config are published together. Do not author a checksum or campaign payload in browser code; read the published value and pass it through unchanged.
type PublishedCampaignConfig = {
v: 1;
i: string; // campaign id
cs: string; // 16-character publish checksum
mode: "builder" | "ladder";
pv: string; // parent variant numeric id
ev: string[]; // eligible variant ids
ep: string[]; // eligible product ids
xv: string[]; // excluded variant ids
mq: number | null; // paid quantity cap value
mqv?: boolean; // true: cap each variant independently
t: Array<{
i: string; label: string; mn: number; mx: number | null;
dt: "pct"; dv: string;
gm: "n" | "o" | "r"; g0: number; g1: number;
gv: string[]; pre: string[]; chg: boolean; few: boolean;
msg?: string; badge?: string;
}>;
disp: Array<{
id: string; pid?: string; t: string;
o?: Array<[string, string]>; img: string | null;
pm: number; cur: string; av: boolean;
bdg?: string[]; rt?: string; rc?: number; sw?: string; h?: string;
}>;
s: string | null; e: string | null;
ea?: string; cd?: boolean; addParentLine: boolean;
sec?: Array<{
i: string; label: string; mn: number; mx: number | null;
ev: string[]; ep: string[];
}>;
};Fields that affect a custom view
| Field | Use | Boundary |
|---|---|---|
ev / ep / xv | Eligible variants, eligible products, and excluded variants. | The Function independently validates eligibility. |
t[] | Percentage steps, item windows, gift rules, messages, and badges. | dv is a decimal string and dt is pct. |
disp[] | Variant/product snapshots, price, images, availability, badges, ratings, swatch color, and product handle. | Display data is capped at 100 products; checkout eligibility is not. Configured sources are snapshotted on publish. |
mq / mqv | The paid-item quantity cap and its optional per-variant scope flag. | Absent or false mqv sums sibling variants per product; true caps each variant independently. |
sec[] | Build-a-box labels, limits, and allowlists. | Membership is first-match in section order. |
s / e / ea / cd | Display schedule and optional countdown state. | Storefront gating is not checkout enforcement. |
Control attributes
The engine delegates click and change handling from the container. IDs must be positive numeric Shopify IDs represented as decimal strings.
| Attribute | Element | Behavior |
|---|---|---|
data-cinch | Container | References a config script ID, or an empty value with nested data-bundle-config JSON. |
data-bundle-toggle | Button | Selects or removes one variant and receives selected/cap attributes. |
data-bundle-product | Same toggle | Associates sibling variants for the default per-product cap; mqv bypasses that grouping. |
data-bundle-inc / data-bundle-dec | Button | Increments or decrements the named variant. |
data-bundle-qty | Input | Sets quantity on change, clamped to campaign and line limits. |
data-bundle-gift | Checkbox | Selects a gift while enforcing tier allowlists, preselection, locks, and min/max. |
data-bundle-gift-reset | Button | Restores the current step's preselected gifts. |
data-bundle-submit | Button | Runs the one-request add, or the verified remove-then-add edit flow. |
Outputs and state
Add data-bundle-out to any element and the engine updates its text. The supported values are count, remaining,tier-label, discount, progress-pct,gift-count, message, error, andqty:VARIANT_ID.
The container receives data-bundle-state withselecting, adding, added, orerror. Submit receives a data-bundle-block code ofempty, no_tier, section_min,gifts_min, or adding when blocked.
Events
Listen for bubbling bundle events to update presentation. The engine also emits Shopify standard cart events before each write and a cart error event when a write fails.
const root = document.querySelector("[data-cinch]");
root?.addEventListener("bundle:change", (event) => {
const {
count, qty, gifts, tierId, tierLabel, discountPct,
remaining, canSubmit, blockCode, status,
} = event.detail;
// Update custom presentation only. The engine owns cart intent.
});
root?.addEventListener("bundle:added", (event) => {
const { bundleId, items, replaced } = event.detail;
});
// Re-scan after your code injects new bundle markup.
window.Cinch?.mountAll();Other verified events are bundle:error with { message },bundle:prefill with{ bundleId, count, gifts, dropped }, andbundle:resync from the view to request a freshbundle:change.
Atomic variant switching
A custom option picker should move the entire selected quantity in one transition. If every unit cannot fit the destination limits, the move is rejected rather than clipped.
root.dispatchEvent(
new CustomEvent("bundle:variant-move", {
bubbles: true,
detail: { from: "4455667788", to: "4455667799" },
}),
);Editing carted bundles
Set data-bundle-edit-param="bundle" to read a valid Cinch bundle ID from?bundle=..., or provide it with data-bundle-edit. A verified prefill stamps data-bundle-editing="true" and emits the prefill event.
Merged bundle components are available to Liquid asline.item_components but are not exposed by AJAX /cart.js. An editing page must emit the documented data-bundle-cart JSON snapshot so the engine can replay merged contents. The custom-page guide includes the shape.
Replacement removes the old group before adding the new one. Restoration after a failed replacement add is best effort, not a transactional Shopify primitive.
Cart and checkout boundary
Never construct the add request or private line properties yourself. The engine stamps _cinch_campaign_id, _cinch_bundle_id,_cinch_tier_id, _cinch_role, and_cinch_config_checksum. The Function validates the whole composition and checksum before returning an operation.
Invalid, stale, or altered hints receive regular pricing. Cinch does not claim to block checkout, and storefront-estimated totals are not the authority.
Limits
- At most 100 storefront-display products are emitted; additional eligible targets can still price.
- A line quantity is capped at 99, and custom bundle sections are capped at five.
- Unavailable display items should not be rendered as selectable controls.
- Fixed bundles use a normal product form and checkout expansion, not this builder contract.
- The current headless asset measures about 6.9 KB Brotli.