Help, manuals and policies
Connect questions and models to resources, applicable policies, accounts and human support.
Model-specific expandable FAQ
Use real compatibility, usage, order and support tasks. Preserve conditions and next steps in each answer. Native details provide a no-script baseline before optional grouping enhancements.
Data and dependencies
- custom.faqs: list.metaobject_reference.
- question is text; answer is rich text; guide is a page reference.
Interaction logic
- Allow keyboard and touch disclosure.
- Keep the answer without inventing a missing guide link.
Example code · snippets/ww-faq.liquid
{% assign questions = product.metafields.custom.faqs.value %}
{% if questions != blank %}
<section aria-labelledby="Questions-{{ section.id }}">
<h2 id="Questions-{{ section.id }}">Questions about this model</h2>
{% for question in questions %}
<details>
<summary>{{ question.question.value | escape }}</summary>
<div>{{ question.answer | metafield_tag }}</div>
{% if question.guide.value != blank %}
<a href="{{ question.guide.value.url | escape }}">Read the guide</a>
{% endif %}
</details>
{% endfor %}
</section>
{% endif %}
Acceptance checks
- Locate the complete answer in initial HTML.
- Verify model, region, version and related pages.
Treat FAQ as readable help content. Do not generate unsuitable FAQPage markup or copy inapplicable terms.
Official documentation
Model index, instructions and manuals
Index manuals by model, version and language. Keep key installation or troubleshooting steps in HTML and offer the full PDF separately, with explicit product/manual relationships.
Data and dependencies
- custom.manuals: list.metaobject_reference.
- model/revision/language are text; instructions is rich text; download is a PDF file reference.
Interaction logic
- Keep verified instructions readable if the file is absent.
- Provide a contact route for an unmatched model.
Example code · snippets/ww-manuals.liquid
{% assign manuals = product.metafields.custom.manuals.value %}
{% if manuals != blank %}
<ul>
{% for manual in manuals %}
{% assign file_url = manual.download.value.url %}
<li>
<h3>{{ manual.model.value | escape }} — {{ manual.revision.value | escape }}</h3>
<p>{{ manual.language.value | escape }}</p>
<div>{{ manual.instructions | metafield_tag }}</div>
{% if file_url != blank %}<a href="{{ file_url | escape }}">Download the manual PDF</a>{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
Acceptance checks
- Download the actual file and check its version.
- Check aliases, language and product backlinks.
The example does not upload manuals. Verify every file and do not substitute a different model manual.
Official documentation
Regional shipping, returns and warranty
Match the region to applicable terms before reusing summaries across product, reassurance and help modules. Re-evaluate after a region change and do not substitute arbitrary terms for an unmatched region.
Data and dependencies
- shop.custom.market_policies: list.metaobject_reference.
- country_code/title/summary are text; policy_page is a page reference.
Interaction logic
- Render only records matching the current country code.
- Provide contact or a policy index when none match.
Example code · snippets/ww-market-policy.liquid
{% assign policies = shop.metafields.custom.market_policies.value %}
{% assign country_code = localization.country.iso_code %}
{% for policy in policies %}
{% if policy.country_code.value == country_code %}
<section>
<h2>{{ policy.title.value | escape }}</h2>
<p>{{ policy.summary.value | escape }}</p>
{% if policy.policy_page.value != blank %}
<a href="{{ policy.policy_page.value.url | escape }}">Read the applicable policy</a>
{% endif %}
</section>
{% endif %}
{% endfor %}
Acceptance checks
- Compare policy text, summary and service ownership.
- Check region changes, return conditions and required evidence.
Country matching is an example. Model multi-country markets, B2B contracts and product exceptions explicitly.
Official documentation
Account self-service and contact forms
Use the platform account route and submit help questions through a labelled native form. Field errors, server acceptance and subsequent human handling are separate states.
Data and dependencies
- routes.account_login_url.
- contact[email], contact[body] and form result.
Interaction logic
- Show success only after posted_successfully?.
- Keep errors near the form without claiming resolution.
Example code · snippets/ww-support-contact.liquid
<a href="{{ routes.account_login_url | escape }}">Open your customer account</a>
{% assign support_form_id = 'Support-' | append: section.id %}
{% form 'contact', id: support_form_id %}
<label for="Email-{{ section.id }}">Email</label>
<input id="Email-{{ section.id }}" name="contact[email]" type="email" autocomplete="email" required>
<label for="Message-{{ section.id }}">Model and question</label>
<textarea id="Message-{{ section.id }}" name="contact[body]" required></textarea>
<button type="submit">Send the question</button>
{% if form.posted_successfully? %}
<p role="status">Your message was submitted.</p>
{% else %}
<div role="alert">{{ form.errors | default_errors }}</div>
{% endif %}
{% endform %}
Acceptance checks
- Test required fields and receipts with approved data.
- Check account configuration, redirects and phone use.
A contact form does not authorize order actions. Keep credentials and sensitive payment data out of public message fields.
Read it, integrate it, verify it
- Choose a module and confirm the data contract.
- Connect the fragment to the current theme or framework.
- Check real variants, markets and recovery states.
Examples target Shopify Online Store 2.0 themes. Headless has separate data and version boundaries. Integrate fragments with actual fields, theme components and locale files.
Architecture references
Original educational examples with Shopify documentation and pinned upstream references. Follow the applicable license when adopting repository code.
References checked 2026-11-12