Appearance
Neart Preset Support Pack
Diagnostic and troubleshooting reference for the Neart wellness/supplements preset — ingredient list, dosage guide, routine builder, how-to-use mode, and supplement metafields.
Includes a dedicated section on Theme Store medical-claim risk avoidance (see below).
FAQ
Q: The dosage calculator shows "NaN" or a wrong result.
A: The dosage calculator reads the Dosage per kg (mg) section setting (dosage_per_kg, default 5), passed to the script via the data-dosage-per-kg attribute. It never reads the uisce_neart.dosage_per_kg product metafield — that metafield feeds only the JSON-LD output and the PDP dosage/ingredient theme blocks. Check:
- Is
Dosage display mode(dosage_mode) set toBody weight calculator? The default isPer serving, which shows static serving guidance and no calculator input. - Is the
Dosage per kg (mg)section setting a sensible number for the product? - Is the calculator mode only used for eligible products (creatine, protein, caffeine — products where weight-based dosing is scientifically supported)?
Note: the Maximum weight (kg) setting controls only the above-range warning threshold — the weight input's HTML max stays fixed at 200 regardless. If the dosage figure in JSON-LD or a PDP block is wrong instead, check the uisce_neart.dosage_per_kg metafield — it must be number_decimal or number_integer type, not a text string like "0.5 mg/kg".
Q: The ingredient list section is empty.
A: The Ingredient List section renders exclusively from its ingredient blocks — it reads no metafields, and its uisce_neart namespace is hardcoded (the section has no namespace setting). Check:
- Are there ingredient blocks added in the theme editor? With zero blocks the section renders nothing on the live storefront (an empty-state hint appears only in the theme editor).
The uisce_neart.ingredients metafield drives a different component: the PDP ingredient-list theme block added on product pages. That metafield is a multi_line_text_field holding comma-separated ingredient names (CSV) — a JSON array pasted there renders as raw text.
Q: "Individual results may vary" disclaimer is not showing.
A: The disclaimer is configured via the Claims disclaimer textarea setting (claims_disclaimer) on the Routine Builder section only. The Dosage Guide has no disclaimer setting — it always renders a fixed healthcare caveat from the sections.dosage_guide.healthcare_caveat locale key. Check:
- In the theme editor, navigate to the Routine Builder section.
- Is the
Claims disclaimerfield populated? The theme ships a default: "Individual results may vary. Food supplements are not intended to diagnose, treat, cure or prevent any disease." - An empty
claims_disclaimerrenders no disclaimer element — clearing the field removes the disclaimer entirely, so replace the default with jurisdiction-appropriate copy rather than deleting it.
Q: The pulse-rhythm animation is visible for customers who have requested reduced motion.
A: This is a critical accessibility issue. The animation is switched off by an @media (prefers-reduced-motion: reduce) { animation: none; } override in assets/preset-neart.css. If the animation shows for customers with prefers-reduced-motion: reduce:
- Check whether a custom CSS edit has removed or overridden the reduced-motion override.
- Check the browser's accessibility settings — some browsers expose this as "Reduce motion" in System Preferences (macOS) or Ease of Access (Windows).
- Test with DevTools: Chrome → Rendering → Emulate CSS media feature →
prefers-reduced-motion: reduce. If animation still plays, the CSS override has been removed.
Q: The aria-live announcement for dosage calculation is not being read by a screen reader.
A: The dosage calculation result uses role="status" with aria-live="polite". Check:
- The live region element must exist in the DOM before the live update occurs (it cannot be inserted dynamically). Verify
<div role="status" aria-live="polite">is in the rendered HTML source. - The result updates synchronously on every input event — there is no debounce or delay. Some screen readers coalesce rapid successive announcements from a polite live region; that is screen-reader behavior, not a theme defect.
- The
aria-describedbyon the weight input references the visually hidden formula description, not the live region (the live region has noid). Do not expect it to point at the result element.
Medical-Claim Risk Avoidance (Theme Store + Regulatory)
This section is mandatory reading for Neart merchants operating in EU/UK/US markets. The Neart preset surfaces dosage and ingredient information. Incorrect wording can:
- Cause your store to be flagged by the Shopify Theme Store review team
- Trigger MHRA (UK), HPRA (IE), or FDA enforcement action on your store's marketing copy
- Cause your Google Shopping feed to be suspended for medical claims
What wording to NOT use
Medical/therapeutic claims (strictly prohibited for food supplements):
| Do NOT use | Why |
|---|---|
| "Treats/cures/prevents [condition]" | Medicinal claim — requires product licence in EU/UK |
| "Clinically proven to reduce [symptom]" | Therapeutic claim — requires evidence dossier |
| "Doctor-recommended dose for [condition]" | Medical authority claim — triggers MHRA borderline review |
| "Take X mg for [disease/disorder]" | Disease claim — prohibited under EU Health Claims Regulation |
| "MedicalRecommendation" in your visible copy | Schema.org type — triggers structured data scrutiny |
| "Prescription-strength formula" | Implies medicinal classification |
Personalised medical framing (risky for dosage guide):
| Risky | Safer alternative |
|---|---|
| "Recommended dose for your weight" | "Suggested serving based on typical adult ranges" |
| "Consult your doctor before changing your dosage" | "Talk to a healthcare professional before changing dosage" (the theme's built-in caveat wording) |
| "Your personalised dosage: X mg" | "Based on {N}kg, typical serving: {serving_size}" |
| "This product has been tested for safety" | "Produced in a GMP-certified facility" |
What wording is SAFE
Per the EU Health Claims Regulation (EC 1924/2006) and DSHEA (US), the following are permitted for authorised nutrient function claims:
- "Magnesium contributes to normal muscle function" (EU authorised claim for Magnesium)
- "Vitamin D contributes to the maintenance of normal bones" (EU authorised)
- "Zinc contributes to normal immune function" (EU authorised)
- "As part of a balanced diet and healthy lifestyle" (general purpose disclaimer)
- "Contains X mg of Magnesium per serving" (factual label statement)
- "Serving size: 2 capsules (400 mg)" (label directions)
- "Store in a cool, dry place. Keep out of reach of children." (storage/safety statement)
Full list of EU authorised health claims: ec.europa.eu/food/safety/labelling_nutrition/ claims/register/public/?event=register.home
How to override copy in admin if jurisdiction differs
The dosage guide's fixed safety copy comes from locale keys that can be customized per locale in the Shopify Translation app:
| Locale key | Purpose | Where it renders |
|---|---|---|
sections.dosage_guide.healthcare_caveat | Always-rendered caveat closing the dosage panel | Both dosage display modes |
sections.dosage_guide.warning_above_range | Non-clinical warning when weight exceeds the threshold | Body weight calculator mode |
To override via the Translation app:
- Shopify Admin → Apps → Translations / Translate & Adapt → select your language.
- Find the section key (e.g.,
sections.dosage_guide.healthcare_caveat). - Enter your jurisdiction-specific text.
The routine builder's disclaimer is not a locale key — edit its Claims disclaimer setting directly in the theme editor (translatable per locale as theme-editor content).
enable_structured_product_usage_data setting
This checkbox on the Dosage Guide and Ingredient List sections gates MedicalRecommendation structured data emission. Leave it false unless:
- Your products are classified as medical devices (Class I or above) under EU MDR 2017/745
- You have a written opinion from a regulatory solicitor confirming the classification
- You are operating as a prescription-dispensing pharmacy (Shopify Health & Medical channel)
For the overwhelming majority of food-supplement merchants: leave it false. The default Product + additionalProperty JSON-LD communicates your dosage and timing data to Google without medical-classification risk (ingredient data is not included in additionalProperty).
Decision Tree: "Why isn't my dosage guide showing data?"
Symptom: Dosage guide renders but shows placeholder text
-> Is serving_size_text set in the section settings?
-> No: set it (e.g., "200mg — Take 1 capsule daily with food"); when blank, nothing renders
on the live storefront (the placeholder appears only in the theme editor)
-> Yes: Continue
-> Is dosage_mode set to "Body weight calculator"?
-> Check section settings; the default is "Per serving" (no calculator input)
-> If it should show a calculator: switch the mode for eligible products only
-> Is the weight input type="number" with inputmode="numeric"?
-> Run the diagnostic snippet below; check 'weightInputPresent'
-> If missing: theme file may be stale; push latest via push-presets.sh
-> Is the Routine Builder's claims_disclaimer empty?
-> Empty disclaimer = no disclaimer element in HTML; add text in section settings
(the dosage guide's healthcare caveat always renders regardless)
-> Not a functional bug, but a compliance requirementValidator Interpretation
"Lighthouse: Dosage guide — form element does not have accessible name"
The weight calculator input must have an accessible label. The theme renders a fixed <label for="dosage-weight-{section id}"> element whose text comes from the sections.dosage_guide.weight_label locale key ("Body weight") — there is no label setting to populate and the label cannot be blank. If Lighthouse flags the input, a custom code edit has removed or detached the label; restore sections/dosage-guide.liquid.
"axe: aria-live region is missing role or aria-live attribute"
The dosage result <div role="status" aria-live="polite"> must exist before the first calculation. If axe flags the live region, verify it is present in the page HTML before JavaScript runs (it should be server-rendered by the Liquid template, not injected by JS).
"Theme Store review flagged 'medical recommendation' language in section"
If the Theme Store review team flags medical-claim wording:
- Review all section
heading,subheading, and block content settings for prohibited phrases (see table above). - Check that
enable_structured_product_usage_dataisfalseon the Dosage Guide and Ingredient List sections (there is no separate JSON-LD section in the editor). - Review the
claims_disclaimertext to ensure it uses non-advisory language (not "talk to your doctor"). - Check blog post content for therapeutic claims — these are not in theme code but are in merchant content and still count for review purposes.
Console Diagnostic Snippet
js
(function neartDiagnostic() {
'use strict';
const dosageGuide = document.querySelector('.dosage-guide');
const weightInput = document.querySelector('input[data-dosage-input]');
const liveRegion = document.querySelector('[role="status"][aria-live]');
const r = {
preset: document.body.className.match(/preset-([a-z]+)/)?.[1] ?? 'unknown',
dosageGuide: {
present: !!dosageGuide,
servingSize: document.querySelector('.dosage-guide__serving-text')?.textContent?.trim() ?? 'not found',
weightInputPresent: !!weightInput,
weightInputType: weightInput?.type ?? 'N/A',
weightInputMode: weightInput?.inputMode ?? 'N/A',
liveRegionPresent: !!liveRegion,
liveRegionRole: liveRegion?.getAttribute('role') ?? 'missing',
caveatPresent: !!document.querySelector('.dosage-guide__caveat'),
},
ingredientList: {
present: !!document.querySelector('.ingredient-list'),
cardCount: document.querySelectorAll('.ingredient-list__card').length,
allergenChips: document.querySelectorAll('.ingredient-list__allergen[role="img"]').length,
},
routineBuilder: {
present: !!document.querySelector('.routine-builder'),
stepCount: document.querySelectorAll('.routine-builder__step').length,
disclaimerPresent: !!document.querySelector('.routine-builder__disclaimer'),
},
pulseAnimation: {
presetCSS: !!document.querySelector('link[href*="preset-neart"]'),
reducedMotionRespected: window.matchMedia('(prefers-reduced-motion: reduce)').matches
? 'reduce — animation should be static'
: 'no preference — animation may play',
},
nicheNamespace: document.querySelector('[data-niche-namespace]')?.dataset?.nicheNamespace ?? 'not found',
medicalJsonLD: Array.from(document.querySelectorAll('script[type="application/ld+json"]')).some((s) =>
s.textContent?.includes('"MedicalRecommendation"'),
),
};
console.group('%cNeart Diagnostic Report', 'color:#8e44ad;font-weight:bold;font-size:14px');
console.table(r.dosageGuide);
console.log('Ingredient list:', r.ingredientList);
console.log('Routine builder:', r.routineBuilder);
console.log('Pulse animation / reduced motion:', r.pulseAnimation);
if (r.medicalJsonLD) {
console.warn(
'⚠ MedicalRecommendation JSON-LD is present — verify enable_structured_product_usage_data is intentional',
);
}
console.groupEnd();
return r;
})();Key checks:
caveatPresent: true— the dosage guide's healthcare caveat always renders with the sectiondisclaimerPresent: true— ensure the routine builder's claims disclaimer is configuredliveRegionPresent: true— required for dosage calculation accessibility (body weight calculator mode only)medicalJsonLD: false— confirm unless explicitly enabled
Curl Cheat-Sheet
bash
# Verify Product + additionalProperty JSON-LD on a supplement product
curl -s "https://your-store.myshopify.com/products/magnesium-400mg" \
| grep -A 10 '"additionalProperty"'
# Check that MedicalRecommendation JSON-LD is NOT present on default products
curl -s "https://your-store.myshopify.com/products/magnesium-400mg" \
| grep '"MedicalRecommendation"'
# Expected: no output (or only in a comment/source reference)
# Verify preset-neart.css is linked
curl -s "https://your-store.myshopify.com" \
| grep 'preset-neart'
# Check niche namespace on dosage page
curl -s "https://your-store.myshopify.com/pages/dosage" \
| grep 'data-niche-namespace'
# Verify ingredient list page exists
curl -o /dev/null -s -w "%{http_code}\n" \
"https://your-store.myshopify.com/pages/ingredients"
# Expected: 200Support pack last updated: 2026-05-03 (Phase 06.10 closeout)