Code Examples

Real-world integration examples for popular platforms and frameworks.

All Examples

Shopify
E-commerce
Liquid template integration with theme blocks
React
Frontend
Modern React app with hooks and TypeScript
Next.js
Full-stack
Server-side rendering with API routes
WooCommerce
E-commerce
WordPress plugin integration
React Native
Mobile
Mobile app integration
Node.js Backend
Backend
Server-side API integration

Shopify Integration

Add virtual try-on to your Shopify store using Liquid templates.

snippets/willitfit-button.liquidliquid
1{%- comment -%}
2 WillItFit Virtual Try-On Button
3 Add this to snippets/willitfit-button.liquid
4{%- endcomment -%}
5
6<div class="willitfit-container"
7 data-product-id="{{ product.id }}"
8 data-product-image="{{ product.featured_image | image_url: width: 800 }}"
9 data-product-title="{{ product.title | escape }}">
10
11 <button type="button"
12 class="btn btn--full btn--secondary willitfit-trigger"
13 aria-label="Try on {{ product.title }} virtually">
14 <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
15 <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/>
16 </svg>
17 Virtual Try-On
18 </button>
19</div>
20
21<script>
22document.addEventListener('DOMContentLoaded', function() {
23 const container = document.querySelector('.willitfit-container');
24 if (!container) return;
25
26 const productId = container.dataset.productId;
27 const productImage = container.dataset.productImage;
28
29 container.querySelector('.willitfit-trigger').addEventListener('click', function() {
30 // Open WillItFit widget
31 window.WillItFitWidget.open({
32 productId: productId,
33 productImage: productImage,
34 onComplete: function(result) {
35 console.log('Try-on completed:', result);
36 }
37 });
38 });
39});
40</script>

React Integration

Build a custom try-on component using React hooks.

useTryOn.tstypescript
1import { useState, useCallback } from 'react';
2import { WillItFit } from '@willitfit/sdk';
3
4const client = new WillItFit({
5 apiKey: process.env.NEXT_PUBLIC_WILLITFIT_API_KEY,
6});
7
8interface TryOnResult {
9 resultImageUrl: string;
10 fitScore: number;
11 recommendations: string[];
12}
13
14export function useTryOn() {
15 const [loading, setLoading] = useState(false);
16 const [error, setError] = useState<string | null>(null);
17 const [result, setResult] = useState<TryOnResult | null>(null);
18
19 const tryOn = useCallback(async (
20 productImageUrl: string,
21 userPhoto: string,
22 category?: string
23 ) => {
24 setLoading(true);
25 setError(null);
26
27 try {
28 const response = await client.tryOn.create({
29 productImageUrl,
30 userPhoto,
31 productCategory: category,
32 });
33
34 setResult({
35 resultImageUrl: response.resultImageUrl,
36 fitScore: response.fitScore,
37 recommendations: response.recommendations || [],
38 });
39
40 return response;
41 } catch (err) {
42 setError(err instanceof Error ? err.message : 'Try-on failed');
43 throw err;
44 } finally {
45 setLoading(false);
46 }
47 }, []);
48
49 const reset = useCallback(() => {
50 setResult(null);
51 setError(null);
52 setLoading(false);
53 }, []);
54
55 return { tryOn, reset, loading, error, result };
56}
57
58// Usage in component
59export function TryOnButton({ productImageUrl, category }: Props) {
60 const [userPhoto, setUserPhoto] = useState<string | null>(null);
61 const { tryOn, loading, result, error, reset } = useTryOn();
62
63 const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
64 const file = e.target.files?.[0];
65 if (file) {
66 const reader = new FileReader();
67 reader.onload = (e) => {
68 setUserPhoto(e.target?.result as string);
69 };
70 reader.readAsDataURL(file);
71 }
72 };
73
74 const handleTryOn = async () => {
75 if (!userPhoto) return;
76 const base64 = userPhoto.split(',')[1];
77 await tryOn(productImageUrl, base64, category);
78 };
79
80 if (result) {
81 return (
82 <div className="text-center">
83 <img src={result.resultImageUrl} alt="Try-on result" />
84 <p className="text-lg font-bold">Fit Score: {result.fitScore}%</p>
85 <button onClick={reset}>Try Another</button>
86 </div>
87 );
88 }
89
90 return (
91 <div>
92 <input type="file" accept="image/*" onChange={handleFileChange} />
93 <button onClick={handleTryOn} disabled={!userPhoto || loading}>
94 {loading ? 'Processing...' : 'Try On'}
95 </button>
96 {error && <p className="text-red-500">{error}</p>}
97 </div>
98 );
99}

Next.js Integration

Server-side API route for secure key handling.

app/api/tryon/route.tstypescript
1// app/api/tryon/route.ts
2import { NextRequest, NextResponse } from 'next/server';
3import { WillItFit } from '@willitfit/sdk';
4
5const client = new WillItFit({
6 apiKey: process.env.WILLITFIT_API_KEY!, // Server-side only
7});
8
9export async function POST(request: NextRequest) {
10 try {
11 const body = await request.json();
12 const { productImageUrl, userPhoto, category } = body;
13
14 // Validate input
15 if (!productImageUrl || !userPhoto) {
16 return NextResponse.json(
17 { error: 'Missing required fields' },
18 { status: 400 }
19 );
20 }
21
22 // Call WillItFit API
23 const result = await client.tryOn.create({
24 productImageUrl,
25 userPhoto,
26 productCategory: category,
27 });
28
29 return NextResponse.json({ success: true, result });
30 } catch (error) {
31 console.error('Try-on error:', error);
32 return NextResponse.json(
33 { error: 'Try-on failed' },
34 { status: 500 }
35 );
36 }
37}

WooCommerce Integration

Add virtual try-on to your WordPress/WooCommerce store.

willitfit-woocommerce.phpphp
1<?php
2/**
3 * Plugin Name: WillItFit Virtual Try-On
4 * Description: Add virtual try-on to WooCommerce products
5 * Version: 1.0.0
6 */
7
8class WillItFit_WooCommerce {
9
10 private $api_key;
11 private $api_url = 'https://api.willitfit.ai/v1';
12
13 public function __construct() {
14 $this->api_key = get_option('willitfit_api_key');
15
16 // Add button to product page
17 add_action('woocommerce_before_add_to_cart_button', [$this, 'render_tryon_button']);
18
19 // Enqueue scripts
20 add_action('wp_enqueue_scripts', [$this, 'enqueue_scripts']);
21
22 // AJAX handler
23 add_action('wp_ajax_willitfit_tryon', [$this, 'handle_tryon']);
24 add_action('wp_ajax_nopriv_willitfit_tryon', [$this, 'handle_tryon']);
25 }
26
27 public function render_tryon_button() {
28 global $product;
29 $image_url = wp_get_attachment_url($product->get_image_id());
30 ?>
31 <div class="willitfit-container" data-product-image="<?php echo esc_url($image_url); ?>">
32 <button type="button" class="button willitfit-trigger">
33 🪄 Virtual Try-On
34 </button>
35 </div>
36 <div id="willitfit-modal" style="display: none;">
37 <!-- Modal content -->
38 </div>
39 <?php
40 }
41
42 public function enqueue_scripts() {
43 if (is_product()) {
44 wp_enqueue_script(
45 'willitfit-widget',
46 'https://cdn.willitfit.ai/widget.js',
47 [],
48 '1.0.0',
49 true
50 );
51
52 wp_localize_script('willitfit-widget', 'willitfit_config', [
53 'api_key' => $this->api_key,
54 'ajax_url' => admin_url('admin-ajax.php'),
55 'nonce' => wp_create_nonce('willitfit_nonce'),
56 ]);
57 }
58 }
59
60 public function handle_tryon() {
61 check_ajax_referer('willitfit_nonce', 'nonce');
62
63 $response = wp_remote_post($this->api_url . '/tryon', [
64 'headers' => [
65 'Authorization' => 'Bearer ' . $this->api_key,
66 'Content-Type' => 'application/json',
67 ],
68 'body' => json_encode([
69 'productImageUrl' => $_POST['product_image'],
70 'userPhoto' => $_POST['user_photo'],
71 ]),
72 ]);
73
74 wp_send_json(json_decode(wp_remote_retrieve_body($response)));
75 }
76}
77
78new WillItFit_WooCommerce();