Therabody
Therabody (Theragun) product catalogue — every device, its variants, its prices and what is in stock — read off the live Shopify storefront.
Domain: therabody.com
Also known as: therabody, Therabody, Theragun
Call it directly
bowmark.providers.therabody.listTheragunProducts(opts?: { limit?: number }): Promise<TherabodyProduct[]>
bowmark.providers.therabody.getTheragunProduct(handle: string): Promise<TherabodyProduct>
bowmark.providers.therabody.recommendTheragun(criteria: { audience?: string; features?: string[]; inStockOnly?: boolean }): Promise<TherabodyRecommendation>Functions
| Function | What it does |
|---|---|
listTheragunProducts | Reads the live Therabody catalogue as Therabody publishes it — every product, its handle, title, vendor, description, tags, images and the per-variant price the storefront is quoting right… |
getTheragunProduct | Reads one product by its handle — every variant, its exact price, the image the storefront is showing and whether that specific variant is purchasable right now. |
recommendTheragun | Filters the live catalogue by what a shopper actually needs — device family, audience, and the features named (percussive, recovery, massage, vibration). Returns the matching products with… |
Types
interface TherabodyVariant {
/** Shopify's numeric variant id as a string. The future addToCart entry. */
id: string;
/** The variant's own label, e.g. "Default Title". */
title: string;
/** Decimal string exactly as the store publishes it, e.g. "54998" (cents). */
price: string;
/** Same scale as price. Null when the product is not on sale. */
compareAtPrice: string | null;
/** The store's own SKU. Null on a product without one. */
sku: string | null;
/** Whether the variant is purchasable right now. */
available: boolean;
options: string[];
}
interface TherabodyProduct {
/** The handle is the only stable identifier across the catalogue. */
handle: string;
title: string;
vendor: string;
productType: string;
url: string;
descriptionHtml: string | null;
optionNames: string[];
variants: TherabodyVariant[];
/**
* The store's own price scale per endpoint — see TherabodyVariant.price for
* why the two strings may differ. Range keeps the same scale as the input.
*/
priceRange: { min: string; max: string } | null;
/** True if ANY variant is purchasable. The "is it in stock?" answer. */
inStock: boolean;
tags: string[];
/** Therabody's own images, in the order the storefront publishes them. */
images: string[];
}
interface TherabodyRecommendation {
/** The matching products, in-stock first, then by handle. */
products: TherabodyProduct[];
/** What the filter DROPPED, in the same register the rest of the library uses. */
warnings: string[];
}Examples
// what are the cheapest Theragun devices in stock right now?
const all = await bowmark.providers.therabody.listTheragunProducts({ limit: 50 });
const inStock = all.filter(p => p.inStock).sort((a, b) => Number(a.priceRange?.min ?? 0) - Number(b.priceRange?.min ?? 0));
log(inStock.slice(0, 5).map(p => `${p.title} from $${p.priceRange?.min}`).join(", "));// what are the variants of this Theragun, and which is left?
const p = await bowmark.providers.therabody.getTheragunProduct("theragun-prime-gen-6-massage-gun-navy");
const left = p.variants.filter(v => v.available);
log(left.length ? left.map(v => v.title).join(", ") : `${p.title} is sold out`);