WooCommerce
There’s no WooCommerce plugin — this is a plain REST integration using the TryOn API and a small
functions.php snippet. Two pieces: a sync step that creates a TryOn product for each WooCommerce
product (using the Woo SKU as external_id), and a template hook that renders the button.
1. Sync products, using the Woo SKU as external_id
Section titled “1. Sync products, using the Woo SKU as external_id”Loop over your WooCommerce catalog via the Woo REST API
and create a matching TryOn product for each one, passing the SKU as external_id so the two
systems stay joined without you having to store TryOn’s own id anywhere:
<?php// Run this from anywhere with WP loaded (WP-CLI command, admin-ajax, cron) — not on// every page load. It's a one-time or periodic sync, not a per-request lookup.
$products = wc_get_products(['limit' => -1, 'status' => 'publish']);
foreach ($products as $product) { $sku = $product->get_sku(); if (!$sku) { continue; // external_id needs something stable — skip products without a SKU }
$response = wp_remote_post('https://api.integration.tryonvirtual.com/v1/products', [ 'headers' => [ 'Authorization' => 'Bearer ' . TRYON_API_KEY, 'Content-Type' => 'application/json', ], 'body' => wp_json_encode([ 'title' => $product->get_name(), 'category' => 'clothes', // map from your product categories/attributes 'external_id' => $sku, 'images' => [wp_get_attachment_url($product->get_image_id())], ]), ]);
// Store a local flag so the template hook below doesn't need a live API // call on every page view — see step 3. if (!is_wp_error($response) && wp_remote_retrieve_response_code($response) === 201) { update_post_meta($product->get_id(), '_tryon_synced', '1'); }}Equivalent as a plain curl loop, if you’re driving this from outside WordPress against a Woo export instead:
# products.json: [{"sku": "SHIRT-XL-RED", "title": "...", "category": "clothes", "image": "..."}]jq -c '.[]' products.json | while read -r p; do curl -X POST https://api.integration.tryonvirtual.com/v1/products \ -H "Authorization: Bearer tryon_sk_your_key" \ -H "Content-Type: application/json" \ -d "$(echo "$p" | jq '{title, category, external_id: .sku, images: [.image]}')"doneEither way, category is required and drives which AI model processes the product — map it from your Woo product categories or attributes, it won’t come from Woo automatically.
2. Enable try-on once images finish processing
Section titled “2. Enable try-on once images finish processing”Same as any other integration — poll or re-check the product until swap_ready is true, then
PATCH to turn it on. The PATCH path needs the TryOn id (a UUID), not the SKU — external_id
only works as a query filter or in the storefront snippet, never in a REST path (see
Using your own IDs). If your sync job already has the id from
the create response in step 1, use that directly; otherwise look it up by SKU first:
# If you only have the SKU: look up the id, then PATCH with itPRODUCT_ID=$(curl -s "https://api.integration.tryonvirtual.com/v1/products?external_id=SHIRT-XL-RED" \ -H "Authorization: Bearer tryon_sk_your_key" | jq -r '.products[0].id')
curl -X PATCH "https://api.integration.tryonvirtual.com/v1/products/$PRODUCT_ID" \ -H "Authorization: Bearer tryon_sk_your_key" \ -H "Content-Type: application/json" \ -d '{"mode": "swap", "tryon_enabled": true}'In the PHP loop from step 1, skip the lookup entirely — decode the create response and reuse the
id it already gave you:
$body = json_decode(wp_remote_retrieve_body($response), true);$tryon_id = $body['product']['id'] ?? null;
if ($tryon_id) { wp_remote_request("https://api.integration.tryonvirtual.com/v1/products/{$tryon_id}", [ 'method' => 'PATCH', 'headers' => [ 'Authorization' => 'Bearer ' . TRYON_API_KEY, 'Content-Type' => 'application/json', ], 'body' => wp_json_encode(['mode' => 'swap', 'tryon_enabled' => true]), ]);}swap_ready still needs a moment to flip to true after images are added — enabling try-on
early is fine (see Product lifecycle),
just don’t render the button until the render check in step 3 confirms both are true.
3. Render the button on the single product page
Section titled “3. Render the button on the single product page”Hook into woocommerce_single_product_summary and use $product->get_sku() as the productId —
the same value you set as external_id during sync:
<?phpadd_action('woocommerce_single_product_summary', function () { global $product; $sku = $product->get_sku(); if (!$sku) { return; }
// Don't call the TryOn API on every page load — check the flag you cached // during sync instead (see step 1). If you need it fresher than your sync // cadence, cache the API response in a transient rather than checking live. if (get_post_meta($product->get_id(), '_tryon_synced', true) !== '1') { return; } ?> <button type="button" data-tryon-product-id="<?php echo esc_attr($sku); ?>">Try On</button> <script async src="https://api.integration.tryonvirtual.com/api/v1/tryon/scripts/embed/bootstrap.js?shop_slug=YOUR_SHOP_SLUG&productId=<?php echo esc_attr(urlencode($sku)); ?>"> </script> <?php}, 25);The _tryon_synced flag above is deliberately coarse — it only tells you a TryOn product exists
for this SKU, not that it’s currently tryon_status: active and swap_ready: true. If your sync
step also enables try-on (step 2) as part of the same job, that’s usually good enough: keep the
flag in sync with reality by only setting it after both create and enable succeed, and clearing it
if a later sync run finds the product isn’t ready. For a setup where readiness can change outside
your sync job (a merchant toggles it off in the panel, say), poll periodically and refresh the
meta rather than trusting it indefinitely — see Storefront integration
for the underlying check.
BigCommerce — the same idea via a Stencil template edit.