PDP Template Build Brief — V3.0

PDP Template Build Brief — V3.0

Sections + Metaobjects approach · Shopify theme build · Prepared for Nim

Contents

  1. Objective
  2. Reference file
  3. Architecture decision
  4. Page layout & structure
  5. Mobile above-fold budget
  6. Section inventory
  7. The repeating purchase block
  8. Metaobject definitions
  9. Product metafield definitions
  10. Product-specific decisions
  11. Technical requirements
  12. CSS strategy
  13. Schema requirements
  14. Build order
  15. Pre-build checks
  16. Do not refactor
  17. Deliverables
  18. Out of scope

1. Objective

Convert the approved PDP mockup (V3.0) into a reusable, admin-editable Shopify PDP template built from Liquid sections and metaobjects. Apply the resulting template to the top 20–30 PDPs by revenue/sessions. Long-tail SKUs remain on the current default PDP template.

The template presents as a traditional Shopify PDP optimized for mobile-first buying: decision-critical elements (image, title, rating, price, pack selector, Add to Cart) visible in the first viewport on a 375×812 screen, with narrative content below the fold and skippable via scanner chips.

Explicitly out of scope

Success criteria

2. Reference file

The approved mockup is pdp-v2-shopify.html (V3.0). It is an annotated, self-contained HTML file scoped under .pdp-v2. Every editable element carries a colored annotation tag showing exactly which field feeds it:

Tag color Meaning Content source
Blue Section setting section.settings.*
Green Metafield (per-product) custom.pdp_* or product object metafields
Purple Metaobject reference References to shared metaobject entries
Orange Product object Native Shopify product data (title, price, images)
Red Block (repeatable) Repeatable blocks in the section schema

The mockup has two toggle buttons in its top bar. "Toggle labels" hides/shows the annotations. "Variant: Without description" switches between the two layout variants Nat reviewed. Neither toggle goes into production — they are review aids only.

3. Architecture decision

Option 1 (Sections + Metaobjects) is confirmed. Do not use Option 2 (product metafields only).

Rationale: several modules are shared across products (how-to steps, FAQ, pain cards, trust badges). Metafields would require duplicating this content on every product record. Metaobjects store it once and let products reference it.

Pattern

4. Page layout & structure

The template is a mobile-first hybrid: decision-critical content above the fold, narrative content below with scanner chips to make it skippable, and the purchase block repeated at natural decision points.

Above the fold (mobile 375×812)

  1. Header (theme-level — search collapsed to icon on PDP only, see section 11)
  2. Campaign banner (one line, gold bottom border)
  3. Hero image (270px cap on mobile)
  4. Thumbnail strip (no tags)
  5. Hero tags (Australian Made pill)
  6. Product title (H1)
  7. Star rating + review count
  8. Price (now / was / save)
  9. Pack selector (40/60 grid, bundle pre-selected)
  10. Add to Cart button
  11. Free-ship callout

Below the fold

  1. Trust block (benefit bullets + 4 trust badges)
  2. Scanner chips (navy bar, 4 anchor chips)
  3. How it works (4 step cards)
  4. Before / after (6-image grid)
  5. Purchase block repeat #1 (after proof)
  6. Stain Nightmare (4 pain cards)
  7. Warning callout (Swim Season Warning)
  8. Instructions (application guide)
  9. Comparison table
  10. Cross-sell (Oxi Shock follow-up)
  11. Reviews (3 manual cards + Okendo carousel placeholder)
  12. Purchase block repeat #2 (after reviews)
  13. FAQ (4-item accordion)
  14. Final CTA band (singular 3+1 offer, no pack selector)

5. Mobile above-fold budget

Target: Add to Cart fully visible at 375×812. Verified positions:

Product Add to Cart position Status
Stain Remover 1kg ~769px ✓ Clear of fold
Black Spot ~792px ✓ Clear of fold

These were measured with the mockup header rendered. Nim must re-verify against the live theme header height at 375px. If the actual header is taller, the fold targets may not hold.

What made the target work

6. Section inventory

Build these as individual .liquid files under /sections/. Each must have its own {% schema %} and appear in the theme editor.

# Section file Purpose Content source
1 pdp-campaign-banner.liquid One-line seasonal hook Section settings
2 pdp-hero.liquid Gallery, title, rating, purchase block Product object + metafields + blocks
3 pdp-scanner-chips.liquid Anchor chip row Section blocks (repeatable)
4 pdp-how-it-works.liquid Science / mechanism steps Metaobject reference list
5 pdp-before-after.liquid 6-image results grid Metaobject reference list
6 pdp-buy-box.liquid Standalone purchase block (used for repeats) Blocks + section settings
7 pdp-pain-cards.liquid Stain Nightmare 4-card grid Metaobject reference list
8 pdp-warning-callout.liquid Swim Season Warning Section settings
9 pdp-instructions.liquid Application guide Product metafield (rich text)
10 pdp-comparison.liquid Comparison table Section blocks (repeatable rows)
11 pdp-cross-sell.liquid Oxi Shock follow-up Product reference metafield
12 pdp-reviews.liquid 3 manual cards + Okendo carousel Blocks + app block embed
13 pdp-faq.liquid Accordion FAQ Metaobject reference list
14 pdp-final-cta.liquid Stock Up and Save band, singular 3+1 offer Section settings + fixed bundle

7. The repeating purchase block

The purchase block appears four times in the template JSON. This is deliberate — it replaces the sticky ATC bar's role of keeping buy one tap away on a long page.

Four instances

Template JSON structure

{
  "sections": {
    "campaign":       { "type": "pdp-campaign-banner" },
    "hero":           { "type": "pdp-hero" },
    "scanner":        { "type": "pdp-scanner-chips" },
    "how_it_works":   { "type": "pdp-how-it-works" },
    "before_after":   { "type": "pdp-before-after" },
    "buy_box_1":      { "type": "pdp-buy-box" },
    "pain_cards":     { "type": "pdp-pain-cards" },
    "warning":        { "type": "pdp-warning-callout" },
    "instructions":   { "type": "pdp-instructions" },
    "comparison":     { "type": "pdp-comparison" },
    "cross_sell":     { "type": "pdp-cross-sell" },
    "reviews":        { "type": "pdp-reviews" },
    "buy_box_2":      { "type": "pdp-buy-box" },
    "faq":            { "type": "pdp-faq" },
    "final_cta":      { "type": "pdp-final-cta" }
  },
  "order": [
    "campaign", "hero", "scanner", "how_it_works", "before_after",
    "buy_box_1", "pain_cards", "warning", "instructions", "comparison",
    "cross_sell", "reviews", "buy_box_2", "faq", "final_cta"
  ]
}

Critical for Nim: the pdp-buy-box section must be fully idempotent. Every DOM ID inside must be instance-scoped (use {{ section.id }} as a prefix). Every JS handler must bind to the section's own container, not to a global selector. The ATC form in each instance must read its own pack selector state. Testing with all three pdp-buy-box instances on one page and changing the pack in one must not affect the others.

What the primary purchase block contains

What the repeats contain

What the final CTA contains

8. Metaobject definitions

Create these in Settings → Custom data → Metaobjects. Enable Storefront access on every definition.

Metaobject type Fields Used by
pdp_step step_number (number), title (text), description (rich text) How it works
pdp_pain_card icon (file), title (text), description (rich text), accent (boolean) Stain Nightmare
pdp_faq question (text), answer (rich text) FAQ
pdp_trust_badge icon (text/SVG name), label (text) Trust block, hero quick benefits

9. Product metafield definitions

Create these in Settings → Custom data → Products. Enable Storefront access.

Namespace.key Type Purpose
custom.pdp_short_description Rich text Hero short description (hidden by default in base variant)
custom.pdp_badge_1 Text Hero tag (e.g. "Australian Made")
custom.pdp_trust_badges List of pdp_trust_badge references Trust badges in buy box
custom.pdp_benefit_bullets List of single-line text Buy box benefit bullets
custom.pdp_steps List of pdp_step references How it works
custom.pdp_before_after_images List of file references Before / after grid
custom.pdp_pain_cards List of pdp_pain_card references Stain Nightmare
custom.pdp_instructions Rich text Application instructions
custom.pdp_cross_sell_product Product reference Cross-sell card
custom.pdp_faqs List of pdp_faq references FAQ accordion

10. Product-specific decisions

No size selector — single-size products

The buy box goes straight from price to pack selector. Multi-variant products handled via a separate optional block if needed later.

Bundle defaults to selected

On page load, the 3+1 bundle is pre-selected. "BEST VALUE" pill only reads "· Selected" when the bundle is active. When single is active, the bundle pill drops the "· Selected" suffix and the single option gains its own navy "Selected" pill.

Mobile pack selector is 40/60 grid

At 599px and below, the pack selector is a two-column grid: 40% for single bottle, 60% for the bundle. Give the pack we want to sell the bigger share. Font sizes scale down on mobile so text fits.

Dynamic free-ship callout

Below the ATC. Bundle selected: "✓ Free shipping unlocked · Ships today". Single selected: "✓ In stock · Ships today". This is JS-driven in the mockup, should be Liquid-driven in the real build.

Campaign banner is one line

"Winter left its marks. Treat them now." Sits above the hero. No B3G1 badge underneath — the offer appears in the pack selector and ATC button, both within a screen.

Thumbnail strip has no tags

No Before / After / Rust pills. The images themselves carry the distinction. Removing them keeps the strip clean and avoids redundancy.

No sticky ATC bar

Removed permanently. The purchase block repeats replace it. Do not build a fixed-position bar.

Base variant: without description

The hero short description is hidden by default. Nim should set the base layout without the description paragraph. The variant toggle in the mockup is a review aid only — it does not go into the production build.

Reviews: 3 manual + Okendo carousel

Three manually curated reviews (driveway, pebblecrete, fibreglass) sit above the Okendo carousel. Below them, the Okendo app block renders the full review feed. No curation pass — all verified reviews flow through.

Okendo carousel placeholder

In the mockup it's a dashed-border block labelled "Okendo Carousel renders here". Nim replaces it with the actual Okendo app block embed via theme app extension.

11. Technical requirements

Header search conditional

On PDP templates, the theme header's search bar collapses to an icon. Everywhere else, it stays full-width. This is a theme-level change, not a section-level one.

{% if template.name == 'product' %}
  <!-- search icon only -->
{% else %}
  <!-- full search bar -->
{% endif %}

The mockup shows the target state visually. Nim builds the actual conditional.

Liquid access patterns

Known limits

Purchase block — instance scoping

Buy box form

Final CTA price sync

The final CTA band shows the bundle price ($179.97). Read this from the bundle variant rather than hardcoding, so if the price changes in admin the final CTA stays in sync.

Cross-sell

The fetchProductData() JS hits /products/{handle}.js for stock and price. Keep it scoped to this section only.

Reviews

The Okendo app block renders below the three manual cards. If the app block isn't present, render only the static review cards and hide the placeholder.

12. CSS strategy

Move shared styles out of the inline <style> tag into a single asset: assets/pdp-modules.css. Link from theme.liquid conditionally when the PDP template is active.

Each section may carry a small <style> block for styles unique to that section only, scoped with a section-specific class prefix. Do not duplicate shared styles.

Use CSS custom properties already defined in the theme's :root for colors, spacing, typography.

Do not port the annotation styles. The .tag, .labeled, .label-strip, .section-badge, .toggle-bar, .header-ref and .header-ref-note classes are mockup aids only. They don't go into the production theme.

13. Schema requirements

Every section must include a {% schema %} block with:

For the buy box:

14. Build order

  1. Define metaobjects and metafields — content team can start entering copy immediately
  2. Build simple sections first: campaign banner, scanner chips
  3. Build the hero — gallery, title, rating, and the primary purchase block
  4. Build the standalone pdp-buy-box section for repeats. Test with two instances on one page before proceeding
  5. Build content sections: how it works, before/after, pain cards, warning, instructions, comparison
  6. Build cross-sell and reviews (with Okendo embed)
  7. Build FAQ and the final CTA band
  8. Assemble the template JSON with all 15 sections in order. Test on one product
  9. Verify above-fold position on a 375×812 device against the live theme header
  10. Migrate the top 20–30 products

15. Pre-build checks

  1. Theme is Online Store 2.0 compatible
  2. Audit existing product metafields for naming collisions
  3. Confirm Storefront access enabled on every metaobject definition and metafield reference
  4. Confirm Okendo is available as a theme app extension block
  5. Check theme's cart drawer behavior — confirm cart:refresh event is supported
  6. Coordinate with theme owner on search collapse — header change, not a section change
  7. Confirm pack selector defaults to 3+1 — verify the pre-selected state renders on load, not just in the mockup
  8. Measure real theme header height at 375px — the above-fold target depends on it

16. Do not refactor

The following elements are working and must be carried into the production build unchanged:

17. Deliverables

  1. 14 Liquid section files under /sections/
  2. Template JSON under /templates/ (e.g. product.pdp.json) with all sections in order
  3. assets/pdp-modules.css with shared styles
  4. Metaobject definitions created and documented
  5. Product metafield definitions created and documented
  6. One product fully populated and rendering correctly as a reference example
  7. Above-fold measurement screenshot on 375×812 confirming the ATC is visible without scrolling
  8. Short handover doc for the content team: which metafields to fill per product, which metaobjects to reference for shared content

18. Out of scope