Published on

How to Build a Trade Platform on Shopify Grow (Without Shopify B2B)

Authors

This guide explains how to implement a trade program for interior designers, architects, and other trade professionals using Shopify Grow and theme-native Liquid — no Shopify Plus B2B required.

If you are a merchant or developer looking to launch a designer/trade portal on a standard Shopify plan, this is a proven pattern you can adapt to your store.

What this pattern builds (and what it does not)

What you get: A lightweight, tag-based trade program that lets qualified professionals apply, submit documents, and shop a curated catalog at trade pricing.

What you do not get: Shopify's native B2B platform (available on Shopify Plus), which includes company accounts, B2B catalogs, payment terms, and quantity rules per company.

This approach works on Shopify Grow because it uses features available on all plans:

LayerMechanism
ApplicationNative {% form 'create_customer' %} with hidden customer tag + note fields
Document uploadShopify Forms app on a follow-up page
Access controlCustomer tag (trade) checked in Liquid
CatalogProduct tag (Trade) filters collection grids
Display pricingsnippets/price.liquid shows discounted price with strikethrough retail
Checkout pricingAutomatic discount + customer segment (configured in Admin)
Trade homeGated page at /pages/trade with custom landing content

Architecture overview

flowchart LR
  prospect[Prospect] --> applyPage["/pages/trade-application"]
  applyPage --> createCustomer["create_customer form"]
  createCustomer --> pendingTag["Tag: trade-pending"]
  createCustomer --> docsPage["/pages/submit-trade-documents"]
  docsPage --> formsApp[Shopify Forms]
  adminReview[Admin review] --> approvedTag["Tag: trade"]
  approvedTag --> tradeHome["/pages/trade"]
  tradeHome --> catalog["Collections filtered by Trade product tag"]
  catalog --> displayPrice["price.liquid 15% display"]
  displayPrice --> checkout["Automatic discount at checkout"]

End-to-end flow:

  1. Prospect visits /pages/trade-application and submits the trade application form.
  2. Shopify creates a customer account tagged trade-pending (recommended) with business details stored in the customer note.
  3. Customer is redirected to /pages/submit-trade-documents to upload resale certificates and other files via Shopify Forms.
  4. Admin reviews the application and uploaded documents in Shopify Admin.
  5. Admin removes trade-pending, adds trade, and optionally marks the customer as tax-exempt.
  6. Approved trade customer logs in, accesses /pages/trade, browses trade-eligible products, sees trade display pricing, and receives the automatic discount at checkout.

Prerequisites

Before implementing this pattern, ensure you have:

  • Shopify Grow (or any plan with customer accounts)
  • Customer accounts enabled (Settings → Customer accounts)
  • Shopify Forms app installed (free) for document collection
  • Online Store 2.0 theme with section support (this guide uses a Dawn-based theme)
  • Theme edit access (code editor or GitHub integration)
  • Products tagged with Trade for trade-eligible SKUs

Optional but recommended:

  • Customer segments for automatic discounts (Customers → Segments)
  • Automatic discounts that target the trade customer segment

Page and template setup

Create three pages in Shopify Admin and assign the correct theme templates.

Page handleURLTemplate suffixTheme file
trade-application/pages/trade-applicationtradetemplates/page.trade.json
submit-trade-documents/pages/submit-trade-documentsForms templatetemplates/page.Forms - Submit Trade documents.json
trade/pages/tradetrade-landingtemplates/page.trade-landing.json

Admin steps

  1. Go to Online Store → Pages → Add page.
  2. Create each page with the handle above.
  3. In the page sidebar, under Theme template, select the matching suffix (trade, trade-landing, or the Forms template).
  4. For the application page, the active section is trade-application-form (configured in page.trade.json).

The application template disables the default page and contact form sections, leaving only the trade application form:

{
  "sections": {
    "main": { "type": "main-page", "disabled": true },
    "form": { "type": "contact-form", "disabled": true },
    "trade_application_form_jWXtze": {
      "type": "trade-application-form",
      "settings": {
        "heading": "Join Today",
        "subheading": "Trade Program",
        "top_cta_text": "Apply for Trade Access",
        "contact_heading": "Apply for Trade Access",
        "description": "<p>Join now or email <strong>trade@yourstore.com</strong> for more information</p>",
        "submit_button_text": "Apply"
      }
    }
  },
  "order": ["main", "form", "trade_application_form_jWXtze"]
}

Add a Trade link to your main navigation menu pointing to /pages/trade-application for prospects, or /pages/trade for logged-in trade customers.

Trade application form

The application form lives in sections/trade-application-form.liquid and uses Shopify's native customer registration form. No third-party app is required for signup.

Custom form vs Shopify Forms

For the application step, Shopify Forms alone would work fine. You can collect business details and documents in a single Forms submission without building a custom theme section. That is the faster path if you want to ship quickly.

This implementation uses a custom create_customer form instead because it matches the application experience to the rest of the storefront — typography, spacing, benefit cards, and section layout all follow the theme's design system. The tradeoff is more theme code to maintain (trade-application-form.liquid + section-trade-application.css), in exchange for a branded, on-site application flow that creates a real customer account in one step.

A practical split that works well:

StepRecommended toolWhy
Application + account creationCustom create_customer form (or Shopify Forms if speed matters more than branding)Custom form creates the customer record and applies tags; Forms is simpler but does not register accounts natively
Document uploadShopify FormsNative file uploads; no reliable file handling in create_customer

If you are starting from scratch and brand polish is not a priority, use Shopify Forms for both steps and manually create customer accounts after review. If the application page is a key conversion surface, the custom form is worth the extra work.

Core form structure

{%- form 'create_customer',
    id: 'TradeApplicationForm',
    class: 'trade-app-form',
    return_to: '/pages/submit-trade-documents'
-%}

  {%- if form.posted_successfully? -%}
    <div class="trade-app-success">
      <h3>Application Submitted</h3>
      <p>Your account has been created! We will review your trade details and contact you shortly.</p>
    </div>
  {%- elsif form.errors -%}
    <div class="trade-app-errors">
      {{ form.errors | default_errors }}
    </div>
  {%- endif -%}

  {%- comment -%}
    Recommended: use trade-pending at signup, not trade.
    Admin adds trade after review.
  {%- endcomment -%}
  <input type="hidden" name="customer[tags]" value="trade-pending">

  {%- comment -%} Standard account fields {%- endcomment -%}
  <input type="text" name="customer[first_name]" required>
  <input type="text" name="customer[last_name]" required>
  <input type="email" name="customer[email]" required>
  <input type="password" name="customer[password]" required>

  {%- endform -%}

Storing business data in customer notes

Shopify's create_customer form does not support custom metafields directly. Instead, use customer[note][Key] fields. Shopify serializes these into the customer's Note field in Admin, where your team can review them during approval.

<fieldset class="trade-app-fieldset">
  <legend class="trade-app-legend">Company Details</legend>

  <input type="text" name="customer[note][Company]" required>
  <input type="url"  name="customer[note][Website]" placeholder="https://">

  <select name="customer[note][Business Type]" required>
    <option value="Interior Designer">Interior Designer</option>
    <option value="Architect">Architect</option>
    <option value="Retailer">Retailer</option>
    <option value="Hospitality">Hospitality</option>
    <option value="Builder/Developer">Builder/Developer</option>
    <option value="Other">Other</option>
  </select>

  <input type="text" name="customer[note][City]" required>
  <input type="text" name="customer[note][State/Province]">
</fieldset>

<fieldset class="trade-app-fieldset">
  <legend class="trade-app-legend">Business Details</legend>

  <select name="customer[note][Annual Volume]">
    <option value="Under $10,000">Under $10,000</option>
    <option value="$10,000 - $50,000">$10,000 - $50,000</option>
    <option value="$50,000 - $100,000">$50,000 - $100,000</option>
    <option value="Over $100,000">Over $100,000</option>
  </select>

  <input type="text" name="customer[note][Tax ID]">
  <input type="text" name="customer[note][Professional Membership ID]" placeholder="ASID, AIA, IIDA, etc.">
</fieldset>

<fieldset class="trade-app-fieldset">
  <legend class="trade-app-legend">Additional Information</legend>

  <textarea name="customer[note][Business Description]"></textarea>

  <input type="checkbox" name="customer[note][Confirmed Business Account]" required>
  <label>I confirm that I am applying for a business account, not a personal consumer account.</label>

  <input type="checkbox" name="customer[accepts_marketing]" checked>
</fieldset>

Section schema and benefits blocks

The form section includes configurable benefit cards via blocks, so merchants can edit copy in the theme editor without touching code:

{
  "name": "Trade Application Form",
  "blocks": [
    {
      "type": "benefit",
      "name": "Benefit Card",
      "settings": [
        { "type": "text", "id": "title", "label": "Heading" },
        { "type": "textarea", "id": "text", "label": "Description" }
      ]
    }
  ]
}

Styles are scoped in assets/section-trade-application.css.

Post-submit redirect

The return_to: '/pages/submit-trade-documents' parameter sends the customer to the document upload page immediately after successful registration — before they can browse the trade catalog.

Document upload step

Native Shopify customer forms do not support file uploads reliably. Use the Shopify Forms app for document collection (resale certificates, business licenses, etc.).

The document page template embeds the Forms app block and a "Proceed to Trade" button:

{
  "sections": {
    "forms": {
      "type": "apps",
      "blocks": {
        "trade_docs_form": {
          "type": "shopify://apps/forms/blocks/inline/8744a304-fcb1-4347-b211-bb6b4759a76a",
          "settings": {
            "form_id": "828092"
          }
        }
      }
    },
    "rich_text_M69p4b": {
      "type": "rich-text",
      "blocks": {
        "button_tNnTKK": {
          "type": "button",
          "settings": {
            "button_label": "Proceed to Trade",
            "button_link": "shopify://pages/trade"
          }
        }
      }
    }
  }
}

Admin steps for Shopify Forms

  1. Install the Shopify Forms app from the App Store.
  2. Create a form with fields for resale certificate upload, business license, and any other required documents.
  3. Copy the form ID from the Forms app and paste it into the theme template's form_id setting.
  4. Assign the Forms template to your /pages/submit-trade-documents page.

Note: The "Proceed to Trade" button links to /pages/trade, which is gated. Pending applicants will be redirected back to the application page until approved — see the next section.

Gating the trade landing page

The trade landing page (/pages/trade) is the authenticated home for approved trade customers. Access is controlled by a lightweight gate section in sections/trade-landing.liquid:

{% comment %} Only approved trade customers may view this page {% endcomment %}
{% if customer and customer.tags contains 'trade' or request.design_mode %}

{% else %}
  <script>
    window.location.href = '/pages/trade-application';
  </script>
{% endif %}
  • customer.tags contains 'trade' — allows only approved trade customers.
  • request.design_mode — allows theme editor preview without logging in.
  • Non-trade and trade-pending customers are redirected to the application page.

The gate section has no visible content of its own. The actual landing page content (hero cards, collection links, etc.) is configured in templates/page.trade-landing.json using standard theme sections like hero-brand-cards-flex and multicolumn.

{
  "sections": {
    "main": { "type": "trade-landing", "settings": {} },
    "hero_brand_cards_flex_RUA3CF": { "type": "hero-brand-cards-flex", "blocks": { } }
  },
  "order": ["main", "hero_brand_cards_flex_RUA3CF"]
}

Trade customer UX touches

Once approved, trade customers get a differentiated experience across the storefront.

Reusable trade customer check

Use this pattern anywhere you need trade-specific logic:

{%- liquid
  assign is_trade_customer = false
  if customer and customer.tags contains 'trade'
    assign is_trade_customer = true
  endif
-%}

Tip: Standardize on lowercase trade for the approved tag. Avoid checking both trade and Trade — pick one casing and use it consistently across all files.

In sections/header.liquid, trade customers clicking the logo go to /pages/trade instead of the retail homepage:

{%- liquid
  assign is_trade_customer = false
  if customer.tags contains 'trade'
    assign is_trade_customer = true
  endif
  assign trade_url = '/pages/trade'
-%}

<a href="{% if is_trade_customer %}{{ trade_url }}{% else %}{{ routes.root_url }}{% endif %}"
   class="header__heading-link">
  {%- comment -%} Logo markup {%- endcomment -%}
</a>

Trade header banner

sections/trade-header-banner.liquid shows a persistent banner for logged-in trade customers. Mount it in your header group (sections/header-group.json):

{%- if customer.tags contains 'trade' or request.design_mode -%}
  <div class="trade-banner">
    <p class="trade-banner__text">{{ section.settings.text }}</p>
  </div>
{%- endif -%}

Default banner text: "Trade Account Active". Height and copy are editable in the theme editor.

Account page label

In sections/main-account.liquid, trade customers see a distinct account title and type:

<h1 class="customer__title">
  {% if customer.tags contains 'trade' %}
    Trade Account
  {% else %}
    {{ 'customer.account.title' | t }}
  {% endif %}
</h1>

{%- if customer.tags contains 'trade' -%}
  <p>Account Type: <strong>Trade Account</strong></p>
{%- endif -%}

Trade catalog filtering

Trade customers should only see products eligible for trade pricing. Filter the collection product grid by a product tag.

In sections/main-collection-product-grid.liquid:

{%- liquid
  assign is_trade_customer = false
  if customer and customer.tags contains 'trade'
    assign is_trade_customer = true
  endif
-%}

{%- for product in collection.products -%}
  {%- assign show_product = true -%}

  {%- if is_trade_customer -%}
    {%- unless product.tags contains 'Trade' -%}
      {%- assign show_product = false -%}
    {%- endunless -%}
  {%- endif -%}

  {%- if show_product -%}
    {% render 'card-product', card_product: product %}
  {%- endif -%}
{%- endfor -%}

Admin workflow for products

  1. Tag every trade-eligible product with Trade in Admin (Products → [product] → Tags).
  2. Retail customers see the full catalog (no filter applied).
  3. Approved trade customers see only products tagged Trade.

Known gap: Search results (sections/main-search.liquid) are not filtered by trade status. Trade customers using search may see non-trade products. Consider adding the same filter to search results as a follow-up.

Display pricing in the theme

Trade display pricing is handled in snippets/price.liquid, which is shared by product cards, product pages, and cart-adjacent UI.

Liquid logic

{%- liquid
  assign is_trade_customer = false
  if customer and customer.tags contains 'trade'
    assign is_trade_customer = true
  endif

  assign trade_discounted_percentage = 0.85
-%}

<div class="price__regular">
  {%- if is_trade_customer -%}
    <span class="price-item price-item--regular h2">
      {{- product.selected_or_first_available_variant.price
          | times: trade_discounted_percentage
          | money -}}
    </span>
  {%- endif -%}

  <span class="price-item price-item--regular h2{% if is_trade_customer %} retail-price{% endif %}">
    {{- product.selected_or_first_available_variant.price | money -}}
  </span>
</div>

For a 15% trade discount, trade_discounted_percentage = 0.85 (customer pays 85% of retail).

Strikethrough retail price styling

In assets/component-price.css:

.price-item.retail-price {
  opacity: 0.5;
  text-decoration: line-through;
  margin-left: 0.5rem;
}

Trade customers see the discounted price prominently, with the original retail price struck through beside it.

Critical: Display pricing is not checkout pricing. Liquid price math runs at render time on the storefront only. It does not change what Shopify charges at checkout. You must configure a matching automatic discount in Admin (next section) so the cart and checkout reflect the same 15% reduction.

Checkout pricing on Grow (Admin setup)

This is the step most merchants miss. Without it, trade customers see discounted prices on product pages but pay full retail at checkout.

Step 1: Create a customer segment

  1. Go to Customers → Segments → Create segment.
  2. Name it Trade Customers.
  3. Add condition: Customer tags → contains → trade.
  4. Save.

Step 2: Create an automatic discount

  1. Go to Discounts → Create discount → Amount off products (or Percentage).
  2. Set method to Automatic.
  3. Set value to 15% (matching your theme's trade_discounted_percentage).
  4. Under Customer eligibility, select Specific customer segments → Trade Customers.
  5. Set Applies to → All products (or limit to collections if needed).
  6. Configure combination rules (whether trade discount stacks with other promotions).
  7. Save and activate.

Step 3: Verify at checkout

  1. Log in as an approved trade customer (trade tag, no trade-pending).
  2. Add a product to cart.
  3. Confirm the automatic discount appears in cart and checkout.
  4. Confirm the discounted total matches what price.liquid displayed on the product page.

Step 4: Tax exemption

For qualified resale transactions, mark the customer as tax-exempt in Admin:

  1. Go to Customers → [customer] → Manage.
  2. Under Tax settings, check Tax exempt.
  3. Save.

This aligns with the "Tax-Exempt Purchasing" benefit shown on the application page. Only enable this after reviewing the customer's resale certificate uploaded via Shopify Forms.

A common launch mistake is applying the trade tag immediately on signup — before admin review. That gives anyone who completes the form instant trade access.

Use a pending → approved tag workflow instead:

StageCustomer tagAccess
Just appliedtrade-pendingCan log in; cannot access /pages/trade or see trade pricing
ApprovedtradeFull trade access, pricing, and catalog
Rejected(remove trade-pending)Standard retail experience

Implementation change (one line in the form)

In sections/trade-application-form.liquid, change the hidden tag field:

{%- comment -%} Before (instant access — not recommended) {%- endcomment -%}
<input type="hidden" name="customer[tags]" value="trade">

{%- comment -%} After (pending until admin approval — recommended) {%- endcomment -%}
<input type="hidden" name="customer[tags]" value="trade-pending">

Ensure all Liquid checks use only trade (not trade-pending) for pricing, catalog filtering, and page gating. The snippets in this guide already follow that pattern.

Admin approval process

  1. Customer submits application → tagged trade-pending, business data in customer note.
  2. Customer uploads documents on /pages/submit-trade-documents.
  3. Admin receives notification (via Shopify Forms submission email or manual check).
  4. Admin reviews customer note fields and uploaded documents.
  5. If approved:
    • Remove tag trade-pending
    • Add tag trade
    • Enable tax-exempt if resale certificate is valid
    • Send approval email to customer
  6. If rejected:
    • Remove tag trade-pending
    • Send rejection email with reason

Optional: Shopify Flow automation

On Shopify Grow, you can use Shopify Flow (if available on your plan) to:

  • Send an internal email when a customer is tagged trade-pending
  • Send an approval email when trade tag is added
  • Create a draft order task for high-volume applicants

Files reference checklist

Use this checklist when implementing or auditing the trade platform in your theme.

Dedicated trade files

FilePurpose
sections/trade-application-form.liquidApplication UI + create_customer form
sections/trade-landing.liquidAccess gate for /pages/trade
sections/trade-header-banner.liquid"Trade Account Active" header banner
assets/section-trade-application.cssApplication form styles
templates/page.trade.jsonApplication page template
templates/page.trade-landing.jsonTrade home page template
templates/page.Forms - Submit Trade documents.jsonDocument upload page template

Modified shared files

FileChange
snippets/price.liquidTrade display pricing (15% off with strikethrough retail)
assets/component-price.css.retail-price strikethrough styling
sections/main-collection-product-grid.liquidFilter products by Trade tag for trade customers
sections/header.liquidLogo links trade customers to /pages/trade
sections/header-group.jsonMounts trade header banner in header group
sections/main-account.liquid"Trade Account" label on account page

Limitations and when to upgrade

Be upfront with your team and trade customers about what this pattern does and does not provide.

What this pattern does well

  • Works on Shopify Grow without Plus
  • No monthly app fees for core functionality
  • Full control over application UX and branding
  • Simple admin workflow using native Shopify customer tools
  • Flat trade discount applied consistently at display and checkout

What this pattern does not provide

  • Company accounts with multiple buyers under one business
  • Per-SKU trade pricing (different discount rates per product or brand)
  • Payment terms (Net 30, Net 60, purchase orders)
  • Quantity price breaks per company
  • Draft order workflows built into the storefront
  • Automatic approval based on document verification
  • Search filtering for trade catalog (not implemented — see catalog section)

When to upgrade to Shopify Plus B2B

Consider Shopify Plus B2B if you need:

  • Multiple users per trade account (buyer, approver, admin roles)
  • Custom catalogs and price lists per company
  • Net payment terms and invoicing
  • High trade order volume requiring automated workflows
  • Integration with ERP or procurement systems

For a curated showroom with a flat trade discount and manual approval, the tag-based Grow pattern is sufficient and significantly simpler to maintain.

Testing checklist

Run through this checklist before launching or after any trade-related theme changes.

Application flow

  • Visit /pages/trade-application as a logged-out user — form renders correctly
  • Submit application with valid data — customer created in Admin
  • Customer tagged trade-pending (not trade) after signup
  • Business fields appear in customer note in Admin
  • Redirect to /pages/submit-trade-documents after successful signup
  • Shopify Forms renders and accepts file upload
  • Form validation errors display correctly (duplicate email, weak password, etc.)

Access control

  • trade-pending customer redirected from /pages/trade to application page
  • Logged-out user redirected from /pages/trade to application page
  • Approved trade customer can access /pages/trade without redirect
  • Theme editor preview works (request.design_mode bypasses gate)

Trade customer experience

  • Trade header banner visible for approved trade customer
  • Logo links to /pages/trade for trade customer, / for retail customer
  • Account page shows "Trade Account" title and account type
  • Collection pages show only products tagged Trade
  • Product pages show discounted price with strikethrough retail
  • Retail customer sees full catalog with no trade pricing

Checkout

  • Automatic 15% discount applied at cart for approved trade customer
  • Discounted cart total matches theme display price
  • Retail customer receives no automatic trade discount
  • Tax-exempt customer not charged tax after Admin tax exemption enabled

Edge cases

  • Search results behavior documented (trade filter not applied — known gap)
  • Customer with both trade-pending and trade tags — verify trade takes precedence
  • Sale/compare-at pricing displays correctly alongside trade discount

Summary

Building a trade platform on Shopify Grow is achievable without Shopify Plus B2B. The pattern is:

  1. Apply with a native create_customer form → tag trade-pending + business data in customer note
  2. Upload docs with Shopify Forms on a follow-up page
  3. Review manually in Admin → swap tag to trade
  4. Gate the trade home page with a Liquid tag check
  5. Filter the catalog with a product tag (Trade)
  6. Display trade pricing in price.liquid
  7. Discount at checkout with an automatic discount tied to a customer segment

The theme handles the experience. Admin handles the business rules. Together they give trade professionals a portal that feels purpose-built — without the complexity or cost of Shopify Plus B2B.

This guide reflects a production Shopify theme implementation. Adapt page handles, discount rates, and form fields to your store.

Subscribe to the newsletter