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 dosage_per_kg from the product metafield (uisce_neart.dosage_per_kg). Check:
- Is
enable_weight_calculatorenabled in the dosage guide section settings? If not, the calculator input will not appear. - Is
uisce_neart.dosage_per_kga decimal/integer metafield value (not a text string like "0.5 mg/kg")? The field must benumber_decimalornumber_integertype. - Is the calculator only enabled for eligible products (creatine, protein, caffeine — products where weight-based dosing is scientifically supported)?
Q: The ingredient list section is empty.
A: The ingredient list renders from blocks OR from the uisce_neart.ingredients metafield (JSON). Check:
- Are there ingredient blocks added in the theme editor?
- If using metafields: is
uisce_neart.ingredientsdefined as ajsonmetafield type and populated with a JSON array on the product? - Is the
niche_metafield_namespaceon the Ingredient List section set touisce_neart?
Q: "Individual results may vary" disclaimer is not showing.
A: The disclaimer is configured via the claims_disclaimer richtext setting on the dosage guide and routine builder sections. Check:
- In the theme editor, navigate to the Dosage Guide or Routine Builder section.
- Is the
Claims disclaimerfield populated with the disclaimer text? - An empty
claims_disclaimerrenders no disclaimer element — there is no default text (each merchant must set their own jurisdiction-appropriate copy).
Q: The pulse-rhythm animation is visible for customers who have requested reduced motion.
A: This is a critical accessibility issue. The animation is gated by @media (prefers-reduced-motion: no-preference) 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 guard.
- 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 guard 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
<span role="status" aria-live="polite">is in the rendered HTML source. - The announcement is delayed 100ms after the weight input changes to debounce rapid typing. Screen readers with fast response times should still hear it; very aggressive announcement throttling in some screen readers may miss it.
- Verify the
aria-describedbyon the weight input references the live region by ID.
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" |
| "Talk to a healthcare professional before changing your dosage" | "Follow the product label and do not exceed the stated daily intake" |
| "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 Neart disclaimer locale keys can be customized per locale in the Shopify Translation app:
| Locale key | Purpose | Jurisdiction |
|---|---|---|
neart.disclaimer.eu_fsd | EU Food Supplement Directive notice | EU stores |
neart.disclaimer.mhra_borderline | MHRA borderline products notice | UK/IE stores |
neart.disclaimer.fda_dshea | FDA DSHEA § 403(r)(6) disclaimer | US stores |
sections.dosage_guide.disclaimer_text | Default dosage safety copy | All locales |
To override via the Translation app:
- Shopify Admin → Apps → Translations / Translate & Adapt → select your language.
- Find the section key (e.g.,
sections.dosage_guide.disclaimer_text). - Enter your jurisdiction-specific text.
enable_structured_product_usage_data setting
This setting 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 ingredient data to Google without medical-classification risk.
Decision Tree: "Why isn't my dosage guide showing data?"
Symptom: Dosage guide renders but shows placeholder text
-> Is serving_size set in the section settings?
-> No: set it (e.g., "2 capsules (400 mg)")
-> Yes: Continue
-> Is enable_weight_calculator enabled?
-> Check section settings; default is false
-> If it should show a calculator: toggle it on 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 claims_disclaimer empty?
-> Empty disclaimer = no disclaimer element in HTML; add text in section settings
-> 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 wires the weight_calculator_label setting as a <label for="dosage-weight"> element. If this is missing, the setting may be blank — populate the Weight calculator label setting in the theme editor.
"axe: aria-live region is missing role or aria-live attribute"
The dosage result <span 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_dataisfalsein the JSON-LD section. - 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-weight]');
const liveRegion = document.querySelector('[role="status"][aria-live]');
const r = {
preset: document.querySelector('meta[name="uisce-preset"]')?.content ?? 'unknown',
dosageGuide: {
present: !!dosageGuide,
servingSize: document.querySelector('[data-serving-size]')?.textContent?.trim() ?? 'not found',
weightInputPresent: !!weightInput,
weightInputType: weightInput?.type ?? 'N/A',
weightInputMode: weightInput?.inputMode ?? 'N/A',
liveRegionPresent: !!liveRegion,
liveRegionRole: liveRegion?.getAttribute('role') ?? 'missing',
disclaimerPresent: !!document.querySelector('.dosage-guide__disclaimer'),
},
ingredientList: {
present: !!document.querySelector('.ingredient-list'),
cardCount: document.querySelectorAll('.ingredient-list__card').length,
allergenChips: document.querySelectorAll('[role="img"].allergen-chip').length,
},
routineBuilder: {
present: !!document.querySelector('.routine-builder'),
slotCount: document.querySelectorAll('.routine-builder__slot').length,
subscriptionNudge: document.querySelectorAll('.subscription-nudge').length,
},
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: !!document
.querySelector('script[type="application/ld+json"]')
?.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:
disclaimerPresent: true— ensure claims disclaimer is configuredliveRegionPresent: true— required for dosage calculation accessibilitymedicalJsonLD: 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)