Code Examples

Complete examples for common integration scenarios.

E-commerce Platform Integration

Swell (Liquid Templates)

<!-- In your product template -->
{% if product.customizable %}
  <div id="product-customizer"
       data-pc-product-id="{{ product.id }}"
       data-pc-store-id="{{ settings.tc_store_id }}"
       data-pc-mode="inline">
  </div>

  <script src="{{ settings.pc_host }}/sdk/product-customizer.js" data-pc-auto-init></script>

  <script>
    ProductCustomizer.registerCallback('handleFinalize', function(data) {
      // Add customized product to cart
      swell.cart.addItem({
        product_id: '{{ product.id }}',
        quantity: 1,
        options: [{
          name: 'Customization',
          value: data.design.id
        }],
        metadata: {
          design_id: data.design.id,
          preview_url: data.previewUrl
        }
      });
    });
  </script>
{% endif %}

ShopStack (Rails/ERB)

<!-- In your product view -->
<% if @product.customizable? %>
  <div id="product-customizer"
       data-pc-product-id="<%= @product.tc_product_id %>"
       data-pc-store-id="<%= Rails.application.credentials.tc_store_id %>"
       data-pc-mode="inline"
       data-pc-on-finalize="handleFinalize">
  </div>

  <script src="<%= ENV['TC_HOST'] %>/sdk/product-customizer.js" data-pc-auto-init></script>

  <script>
    ProductCustomizer.registerCallback('handleFinalize', async function(data) {
      const response = await fetch('/cart/add', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content
        },
        body: JSON.stringify({
          product_id: '<%= @product.id %>',
          design_id: data.design.id,
          preview_url: data.previewUrl
        })
      });

      if (response.ok) {
        window.location.href = '/cart';
      }
    });
  </script>
<% end %>

Full API Integration Example

Node.js/Express Backend

const express = require('express');
const fetch = require('node-fetch');

const TC_API_KEY = process.env.TC_API_KEY;
const TC_BASE_URL = process.env.TC_BASE_URL || 'https://trucustom.net';

const app = express();
app.use(express.json());

// Fetch products with customization enabled
app.get('/api/customizable-products', async (req, res) => {
  try {
    const response = await fetch(`${TC_BASE_URL}/api/v1/products?customizable=true`, {
      headers: {
        'Authorization': `Bearer ${TC_API_KEY}`,
        'Content-Type': 'application/json'
      }
    });

    const data = await response.json();
    res.json(data);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Create a design
app.post('/api/designs', async (req, res) => {
  const { productId, canvasData } = req.body;

  try {
    const response = await fetch(`${TC_BASE_URL}/api/v1/designs`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${TC_API_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        design: {
          product_id: productId,
          canvas_data: canvasData
        }
      })
    });

    const data = await response.json();
    res.json(data);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Finalize a design
app.post('/api/designs/:id/finalize', async (req, res) => {
  const { id } = req.params;

  try {
    const response = await fetch(`${TC_BASE_URL}/api/v1/designs/${id}/finalize`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${TC_API_KEY}`,
        'Content-Type': 'application/json'
      }
    });

    const data = await response.json();
    res.json(data);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Webhook handler
app.post('/webhooks/pc', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-pc-signature'];

  // Verify signature (see webhooks docs)
  // ...

  const event = JSON.parse(req.body);

  switch (event.event) {
    case 'design.finalized':
      // Process finalized design
      console.log('Design finalized:', event.data.id);
      // Update order, send confirmation, etc.
      break;
  }

  res.status(200).send('OK');
});

app.listen(3000);

Python/Flask Backend

import os
import requests
from flask import Flask, request, jsonify

app = Flask(__name__)

TC_API_KEY = os.environ.get('TC_API_KEY')
TC_BASE_URL = os.environ.get('TC_BASE_URL', 'https://trucustom.net')

headers = {
    'Authorization': f'Bearer {TC_API_KEY}',
    'Content-Type': 'application/json'
}

@app.route('/api/customizable-products')
def get_products():
    response = requests.get(
        f'{TC_BASE_URL}/api/v1/products',
        headers=headers,
        params={'customizable': 'true'}
    )
    return jsonify(response.json())

@app.route('/api/designs', methods=['POST'])
def create_design():
    data = request.json
    response = requests.post(
        f'{TC_BASE_URL}/api/v1/designs',
        headers=headers,
        json={
            'design': {
                'product_id': data['product_id'],
                'canvas_data': data.get('canvas_data', {})
            }
        }
    )
    return jsonify(response.json())

@app.route('/api/designs/<design_id>/finalize', methods=['POST'])
def finalize_design(design_id):
    response = requests.post(
        f'{TC_BASE_URL}/api/v1/designs/{design_id}/finalize',
        headers=headers
    )
    return jsonify(response.json())

@app.route('/webhooks/pc', methods=['POST'])
def webhook():
    # Verify signature (see webhooks docs)
    event = request.json

    if event['event'] == 'design.finalized':
        design_id = event['data']['id']
        # Process finalized design
        print(f'Design finalized: {design_id}')

    return 'OK', 200

if __name__ == '__main__':
    app.run(port=3000)

Frontend React Integration

import React, { useEffect, useRef } from 'react';

function ProductCustomizer({ productId, storeId, onFinalize }) {
  const containerRef = useRef(null);
  const instanceRef = useRef(null);

  useEffect(() => {
    // Load SDK if not already loaded
    if (!window.ProductCustomizer) {
      const script = document.createElement('script');
      script.src = 'https://trucustom.net/sdk/product-customizer.js';
      script.onload = initCustomizer;
      document.body.appendChild(script);
    } else {
      initCustomizer();
    }

    function initCustomizer() {
      instanceRef.current = window.ProductCustomizer.init({
        container: containerRef.current,
        productId,
        storeId,
        mode: 'inline',
        onFinalize: (data) => {
          onFinalize?.(data);
        }
      });
    }

    return () => {
      // Cleanup on unmount
      if (instanceRef.current) {
        window.ProductCustomizer.close(instanceRef.current.id);
      }
    };
  }, [productId, storeId]);

  return <div ref={containerRef} style={{ height: '700px' }} />;
}

// Usage
function ProductPage({ product }) {
  const handleFinalize = async (data) => {
    await addToCart({
      productId: product.id,
      designId: data.design.id,
      previewUrl: data.previewUrl
    });
  };

  return (
    <div>
      <h1>{product.name}</h1>
      <ProductCustomizer
        productId={product.pcProductId}
        storeId={process.env.REACT_APP_TC_STORE_ID}
        onFinalize={handleFinalize}
      />
    </div>
  );
}

More Examples

Check out our SDK example page for live, interactive examples.