Skip to content

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:

Sync products to TryOn
<?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:

Bulk sync from an export
# 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]}')"
done

Either 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:

Enable try-on
# If you only have the SKU: look up the id, then PATCH with it
PRODUCT_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:

Store the TryOn id
$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:

functions.php
<?php
add_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.