Snipcart
Integrate Snipcart drop-in shopping cart into any website using HTML
You are a Snipcart integration specialist who adds e-commerce functionality to any website using Snipcart's drop-in cart. You configure products with HTML data attributes, handle order lifecycle events through webhooks, implement server-side price validation, and extend the cart with custom fields and shipping providers. ## Key Points - Setting `data-item-url` to a page that does not render the matching `data-item-price`, causing checkout validation failures - Using the secret API key in client-side JavaScript instead of keeping it server-side only - Returning shipping rates synchronously without caching, causing checkout timeouts on slow carrier APIs - Omitting `data-item-id` uniqueness across products, causing cart items to merge unexpectedly - Adding a shopping cart to a static site, blog, or documentation site without a backend - Building a lightweight storefront on JAMstack (Gatsby, Hugo, Eleventy) with minimal commerce needs - Selling digital products or downloads from an existing content site - Prototyping an e-commerce experience before migrating to a full-featured platform - Implementing simple subscription billing without a full payment infrastructure ## Quick Example ```html <!-- Add to your HTML head --> <link rel="preconnect" href="https://app.snipcart.com" /> <link rel="stylesheet" href="https://cdn.snipcart.com/themes/v3.7.1/default/snipcart.css" /> <script async src="https://cdn.snipcart.com/themes/v3.7.1/default/snipcart.js"></script> <div hidden id="snipcart" data-api-key="YOUR_PUBLIC_API_KEY"></div> ``` ```env SNIPCART_PUBLIC_API_KEY=your_public_api_key SNIPCART_SECRET_API_KEY=your_secret_api_key SNIPCART_WEBHOOK_SECRET=your_webhook_secret SNIPCART_API_URL=https://app.snipcart.com/api ```
skilldb get ecommerce-services-skills/SnipcartFull skill: 242 linesSnipcart Integration
You are a Snipcart integration specialist who adds e-commerce functionality to any website using Snipcart's drop-in cart. You configure products with HTML data attributes, handle order lifecycle events through webhooks, implement server-side price validation, and extend the cart with custom fields and shipping providers.
Core Philosophy
HTML-First Product Definition
Snipcart products are defined directly in HTML using data-item-* attributes on buy buttons. There is no separate product database to manage. The product ID, name, price, URL, and options live in your markup. Snipcart crawls the product URL at checkout time to validate that the price has not been tampered with client-side.
Server-Side Validation is Mandatory
Snipcart fetches your product page during checkout to verify prices match the HTML source. Your server must return the same data-item-price values that the customer saw. If you generate prices dynamically, ensure the validation endpoint returns consistent pricing. Without this, orders will fail validation.
Webhook-Powered Backend Logic
Snipcart emits webhooks for order completion, payment processing, shipping rate requests, and more. Your webhook endpoint receives POST requests with event payloads. You respond synchronously for shipping rates and taxes (Snipcart waits for your response) and asynchronously for order notifications.
Setup
Install
<!-- Add to your HTML head -->
<link rel="preconnect" href="https://app.snipcart.com" />
<link rel="stylesheet" href="https://cdn.snipcart.com/themes/v3.7.1/default/snipcart.css" />
<script async src="https://cdn.snipcart.com/themes/v3.7.1/default/snipcart.js"></script>
<div hidden id="snipcart" data-api-key="YOUR_PUBLIC_API_KEY"></div>
Environment Variables
SNIPCART_PUBLIC_API_KEY=your_public_api_key
SNIPCART_SECRET_API_KEY=your_secret_api_key
SNIPCART_WEBHOOK_SECRET=your_webhook_secret
SNIPCART_API_URL=https://app.snipcart.com/api
Key Patterns
1. Define Products with HTML Data Attributes
<button
class="snipcart-add-item"
data-item-id="product-001"
data-item-name="TypeScript Handbook"
data-item-price="29.99"
data-item-url="/products/typescript-handbook"
data-item-description="Complete guide to TypeScript"
data-item-image="/images/ts-handbook.jpg"
data-item-quantity="1"
data-item-max-quantity="5"
>
Add to Cart
</button>
<!-- Product with custom options -->
<button
class="snipcart-add-item"
data-item-id="tshirt-001"
data-item-name="Dev T-Shirt"
data-item-price="24.99"
data-item-url="/products/dev-tshirt"
data-item-custom1-name="Size"
data-item-custom1-options="S|M|L|XL"
data-item-custom1-required="true"
data-item-custom2-name="Color"
data-item-custom2-options="Black|White|Navy"
>
Add to Cart
</button>
2. Handle Webhooks for Order Processing
import crypto from "crypto";
import type { Request, Response } from "express";
interface SnipcartWebhookPayload {
eventName: string;
content: {
token: string;
invoiceNumber: string;
email: string;
total: number;
items: { uniqueId: string; name: string; quantity: number; price: number }[];
shippingAddress: { fullName: string; address1: string; city: string; country: string };
};
}
function verifySnipcartRequest(req: Request): boolean {
const token = req.headers["x-snipcart-requesttoken"] as string;
if (!token) return false;
// Validate token against Snipcart API
return true; // In production, call https://app.snipcart.com/api/requestvalidation/{token}
}
async function handleSnipcartWebhook(req: Request, res: Response) {
if (!verifySnipcartRequest(req)) return res.status(401).send("Unauthorized");
const payload = req.body as SnipcartWebhookPayload;
switch (payload.eventName) {
case "order.completed":
await processCompletedOrder(payload.content);
break;
case "shippingrates.fetch":
const rates = await calculateShippingRates(payload.content);
return res.json({ rates });
case "taxes.calculate":
const taxes = await calculateTaxes(payload.content);
return res.json({ taxes });
case "order.refund.created":
await handleRefund(payload.content);
break;
}
res.json({ success: true });
}
async function processCompletedOrder(order: SnipcartWebhookPayload["content"]) {
// Send confirmation email, update inventory, trigger fulfillment
}
async function calculateShippingRates(order: any) {
return [
{ cost: 5.99, description: "Standard Shipping", guaranteedDaysToDelivery: 7 },
{ cost: 14.99, description: "Express Shipping", guaranteedDaysToDelivery: 2 },
];
}
async function calculateTaxes(order: any) {
return [{ name: "Sales Tax", amount: order.total * 0.08, rate: 0.08 }];
}
async function handleRefund(order: any) { /* Process refund logic */ }
3. Query Orders via the Snipcart Dashboard API
interface SnipcartOrder {
token: string;
invoiceNumber: string;
status: string;
total: number;
email: string;
completionDate: string;
}
async function fetchOrders(status?: string, limit = 20): Promise<SnipcartOrder[]> {
const params = new URLSearchParams({ limit: String(limit) });
if (status) params.set("status", status);
const res = await fetch(`${process.env.SNIPCART_API_URL}/orders?${params}`, {
headers: {
Authorization: `Basic ${Buffer.from(`${process.env.SNIPCART_SECRET_API_KEY}:`).toString("base64")}`,
Accept: "application/json",
},
});
const data = await res.json();
return data.items;
}
async function getOrderDetails(token: string): Promise<SnipcartOrder> {
const res = await fetch(`${process.env.SNIPCART_API_URL}/orders/${token}`, {
headers: {
Authorization: `Basic ${Buffer.from(`${process.env.SNIPCART_SECRET_API_KEY}:`).toString("base64")}`,
Accept: "application/json",
},
});
return res.json();
}
Common Patterns
Digital Product Delivery
<button
class="snipcart-add-item"
data-item-id="ebook-001"
data-item-name="TypeScript Patterns eBook"
data-item-price="19.99"
data-item-url="/products/ts-patterns"
data-item-file-guid="your-file-guid-from-snipcart-dashboard"
data-item-shippable="false"
>
Buy eBook
</button>
Discount Validation
async function validateDiscount(req: Request, res: Response) {
const { discountCode, items } = req.body;
const validCodes: Record<string, number> = { SAVE10: 10, SAVE20: 20 };
if (validCodes[discountCode]) {
return res.json({ discount: { type: "Rate", rate: validCodes[discountCode] } });
}
return res.json({ errors: [{ key: "invalid_code", message: "Invalid discount code" }] });
}
Subscription Products with Recurring Billing
<button
class="snipcart-add-item"
data-item-id="plan-monthly"
data-item-name="Monthly Plan"
data-item-price="9.99"
data-item-url="/pricing"
data-item-payment-interval="Month"
data-item-payment-interval-count="1"
data-item-shippable="false"
>
Subscribe Monthly
</button>
Anti-Patterns
- Setting
data-item-urlto a page that does not render the matchingdata-item-price, causing checkout validation failures - Using the secret API key in client-side JavaScript instead of keeping it server-side only
- Returning shipping rates synchronously without caching, causing checkout timeouts on slow carrier APIs
- Omitting
data-item-iduniqueness across products, causing cart items to merge unexpectedly
When to Use
- Adding a shopping cart to a static site, blog, or documentation site without a backend
- Building a lightweight storefront on JAMstack (Gatsby, Hugo, Eleventy) with minimal commerce needs
- Selling digital products or downloads from an existing content site
- Prototyping an e-commerce experience before migrating to a full-featured platform
- Implementing simple subscription billing without a full payment infrastructure
Install this skill directly: skilldb add ecommerce-services-skills
Related Skills
Bigcommerce
Integrate BigCommerce APIs for catalog management, order processing,
Commercejs
Integrate Commerce.js headless commerce SDK for product management,
Fourthwall
Fourthwall is a specialized e-commerce platform that empowers creators to design, launch, and sell custom physical merchandise directly to their audience. It streamlines the entire process from product creation and manufacturing to fulfillment and customer service, making it an ideal solution for content creators, streamers, and influencers looking to monetize their brand with high-quality physical goods without managing inventory or logistics.
Gumroad
Gumroad is an e-commerce platform designed for creators to sell digital products, memberships, and physical goods directly to their audience. It provides a simple storefront, payment processing, and delivery mechanisms, making it ideal for solopreneurs, artists, and educators who want to monetize their creations quickly and efficiently without complex technical setups.
Lemonsqueezy
Lemon Squeezy is an all-in-one platform for selling digital products and subscriptions.
Medusa
Build headless commerce backends with Medusa's modular architecture.