BadgerFy.ai Docs

Order Data

Order data is a specialized data source type designed for the Recommendation Strip widget. Unlike traditional text-based data sources, order data uses structured CSV or JSON to store purchase history, enabling the AI to analyze buying patterns and generate intelligent product recommendations.

đź’ˇ Recommendation Strip Only

Order data sources are exclusively used with Recommendation Strip agents. They cannot be used with AI Assistant, Quiz, or Nudge agents, which require standard file uploads or website scrapes.

Upload Options

There are two ways to upload order data: Standard Upload (requires data in the exact schema format) and AI-Assisted Upload (automatically maps your fields).

Standard Upload (Recommended)

For maximum accuracy and full control over your data, use the Upload Order Data tab with data pre-formatted to match the schema documented below. Standard upload is recommended when:

  • You need precise control over how your data is structured
  • You want to include custom metadata fields at order or product levels
  • You've already formatted your data to match our schema
  • You need guaranteed accuracy for production use

AI-Assisted Upload

The AI-Assisted Upload option allows you to upload order data exports as-is from most e-commerce platforms. Our AI analyzes your file structure and automatically maps your fields to the required schema format. This is useful for quickly importing data without manual formatting.

🤖 How It Works

Upload up to 3 CSV or JSON files, give your dataset a name, and let the AI transform your data. The AI identifies fields like order IDs, dates, product names, prices, and URLs—even if they use different column names than our schema.

⚠️ AI Limitations — Always Verify Your Data

AI-assisted mapping is not perfect. After processing, review your data in the Preview panel to ensure accuracy. Common issues to check:

  • Product URLs: Verify productPath values match your actual product page URLs
  • Prices: Confirm prices are correctly extracted and formatted
  • Categories: Check that category assignments are accurate
  • Thumbnail URLs: Ensure image URLs are valid and accessible

Correcting AI-Mapped Data

If you notice systematic errors in your AI-processed data (e.g., incorrect URL patterns), you have several options:

  • Fix Source Data: Correct your original export file and re-upload using AI-Assisted Upload again
  • Use Find & Replace: In spreadsheet software, use find and replace to fix URL patterns before uploading (e.g., replace /p/ with/products/)
  • Standard Upload: Pre-format your data to match the exact schema documented below and use the standard Upload tab

Import with Integration

If you have a connected integration (Shopify, BigCommerce, or WooCommerce), you can import order data directly from your store using the Import Data tab. This pulls your order history directly from the platform API and automatically converts it to the required schema format.

  • Shopify: Imports orders via the Shopify Admin API
  • BigCommerce: Imports orders via the BigCommerce API
  • WooCommerce: Imports orders via the WooCommerce REST API

Integration imports are processed in the background. Once complete, you can preview the data, download it for review, and confirm the upload. This is the easiest way to get started if you have a supported e-commerce platform.

See the Integrations documentation for setup instructions for each platform.

Supported File Formats

Order data sources accept both CSV and JSON files. CSV files are automatically converted to JSON when uploaded. For standard uploads, your data must match the required schema format documented below.

CSV Format

CSV files work well for exports where each row represents one line item. Products with the same order ID will be automatically grouped into a single order.

orderId,orderDate,displayName,productPath,category,productCode,sku,thumbUrl,purchasePrice,orderValue,currency,quantity
ORD-12345,2024-01-15T10:30:00Z,Wireless Bluetooth Headphones,/products/wireless-headphones,Electronics,WBH-001,WBH-001-BLK,https://example.com/images/headphones.jpg,79.99,159.98,USD,1
ORD-12345,2024-01-15T10:30:00Z,USB-C Charging Cable,/products/usb-c-cable,Electronics,USB-001,USB-001-WHT,https://example.com/images/cable.jpg,19.99,159.98,USD,2
ORD-67890,2024-01-16T14:22:00Z,Running Shoes Pro,/products/running-shoes,Footwear,RS-500,RS-500-BLU,https://example.com/images/shoes.jpg,129.99,129.99,USD,1

Tip: Rows with the same orderId will be automatically grouped, with each row becoming a product in that order.

JSON Format

JSON format is ideal when your data is already structured with orders containing nested product arrays.

Example Structure

[
{
"orderId": "ORD-12345",
"orderDate": "2024-01-15T10:30:00Z",
"orderValue": "92.98",
"currency": "USD",
"metadata": { "source": "website", "campaign": "summer-sale" },
"products": [
{
"displayName": "Wireless Bluetooth Headphones",
"productPath": "/products/wireless-headphones",
"category": "Electronics",
"productCode": "WBH-001",
"sku": "WBH-001-BLK",
"thumbUrl": "https://example.com/images/headphones.jpg",
"purchasePrice": "79.99",
"quantity": 1
},
{
"displayName": "USB-C Charging Cable",
"productPath": "/products/usb-c-cable",
"category": "Accessories",
"productCode": "USBC-002",
"sku": "USBC-002-6FT",
"thumbUrl": "https://example.com/images/cable.jpg",
"purchasePrice": "12.99",
"quantity": 1,
"metadata": { "variant": "6ft-white" }
}
]
},
{
"orderId": "ORD-12346",
"orderDate": "2024-01-16T14:22:00Z",
"orderValue": "59.98",
"currency": "USD",
"products": [
{
"displayName": "Wireless Mouse",
"productPath": "/products/wireless-mouse",
"category": "Electronics",
"productCode": "WM-003",
"sku": "WM-003-WHT",
"thumbUrl": "https://example.com/images/mouse.jpg",
"purchasePrice": "29.99",
"quantity": 2
}
]
}
]

Required Fields

Every order and product must include the following fields:

Order Level

  • orderId — Unique identifier for the order (string)
  • orderDate — Order date in ISO 8601 format (string)
  • orderValue — Total order value as a string (e.g., "129.99" or "1299")
  • currency — ISO 4217 currency code (3-letter uppercase, e.g., "USD", "EUR", "GBP")
  • products — Array of product objects (at least one required)
  • metadata — Optional object for custom fields (e.g., source, campaign)
đź’± Supported Currency Codes

The currency field accepts standard ISO 4217 currency codes. Common codes include: USD (US Dollar), EUR (Euro), GBP (British Pound), JPY (Japanese Yen), AUD (Australian Dollar), CAD (Canadian Dollar), CHF (Swiss Franc), CNY (Chinese Yuan), INR (Indian Rupee), BRL (Brazilian Real), and many more.

Product Level

  • displayName — Product name shown in the recommendation strip
  • productPath — URL path to the product page (e.g., "/products/my-item")
  • category — Product category (used for recommendation grouping)
  • productCode — Parent product identifier
  • sku — Specific variant SKU
  • thumbUrl — URL to a 1:1 aspect ratio product thumbnail
  • purchasePrice — Unit price as a string (e.g., "29.99" or "$29.99")
  • quantity — Number of units purchased (integer, minimum 1)
  • metadata — Optional object for custom fields (e.g., variant info)

Data Requirements

For optimal recommendation quality, ensure your order data meets these guidelines:

  • Minimum Orders: At least 1,000 orders recommended for accurate pattern detection
  • History Depth: Include at least 3 months of order history
  • Valid Orders Only: Exclude cancelled, refunded, or incomplete orders
  • Consistent Categories: Use standardized category names across all products
  • Valid URLs: Ensure all product and thumbnail URLs are accessible
  • Duplicate Prevention: Orders with duplicate orderId values are automatically skipped during processing, so you can safely re-upload files without creating duplicate entries

Automatic Order Capture

In addition to manual file uploads, you can automatically capture order data from your store's confirmation page using the embedded widget's JavaScript API. This keeps your data source continuously updated with new purchases.

Using the addOrder API

The window.badgerfyai.addOrder() method allows you to submit order data directly from your order confirmation page:

// Call this on your order confirmation page
window.badgerfyai.addOrder('YOUR_DATASOURCE_ID', {
orderId: 'ORD-12345',
orderDate: new Date().toISOString(),
orderValue: '79.99',
currency: 'USD',
metadata: { source: 'website' },
products: [
{
displayName: 'Wireless Bluetooth Headphones',
productPath: '/products/wireless-headphones',
category: 'Electronics',
productCode: 'WBH-001',
sku: 'WBH-001-BLK',
thumbUrl: 'https://yourstore.com/images/headphones.jpg',
purchasePrice: '79.99',
quantity: 1
}
]
}).then(result => {
if (result.success) {
console.log('Order submitted successfully');
} else {
console.error('Failed to submit order:', result.message);
}
});
⚠️ Data Source ID Required

The addOrder() method requires your order data source ID (encoded). You can find this ID in your data source settings in the dashboard.

API Response

The addOrder() method returns a promise that resolves to an object with the following properties:

  • success — Boolean indicating if the order was queued
  • message — Human-readable status message
  • errors — Array of validation errors (if applicable)

Validation

Orders are validated before submission. Common validation errors include:

  • Missing required fields (orderId, orderDate, orderValue, currency, products)
  • Empty products array
  • Invalid thumbnail URL format
  • Invalid or negative purchase price or order value
  • Invalid or missing quantity (must be at least 1)
  • Invalid currency code (must be a valid ISO 4217 3-letter code like USD, EUR, GBP)

Consumer API

For bulk uploads and automated data pipelines, Pro and Business plan users can upload order data programmatically using the Consumer API. This is ideal for syncing large batches of historical orders or integrating with your backend systems.

đź“‹ Plan Requirement

The Consumer API is available on Pro and Business plans only. Basic plan users can use the dashboard file upload or the addOrder() widget method.

⚠️ Exact Schema Required

Both dashboard and API uploads require data in the exact schema format documented above. Ensure your JSON matches the required field names and structure for successful processing.

The API supports both creating new order data and updating existing datasets with zero downtime—your recommendation strips continue using the current data until new uploads are fully processed.

See the Consumer API documentation for complete endpoint details, authentication, and example automation scripts.

Storage Management

Order data counts toward your plan's storage limits. As your order history grows, you may need to manage storage to stay within your plan's allocation.

Plan Storage Limits

  • Basic Plan: 50MB maximum total storage
  • Pro Plan: 100MB maximum total storage
  • Business Plan: 500MB maximum total storage

Clearing Old Orders

To free up storage space, you can periodically remove older order data using the Clear Storage Options button on the data source upload page. This allows you to:

  • Remove orders older than a specified date
  • Clear all order data and start fresh
  • Delete specific order files while keeping others
đź’ˇ Recommended Practice

We recommend keeping 6–12 months of order history for optimal recommendations. Orders older than this typically have diminishing impact on recommendation quality and can be safely cleared to free up storage.

Platform Integration Guides

The following examples demonstrate how to extract order data from popular e-commerce platforms and transform it to the required format. These scripts can be run as scheduled jobs to keep your order data synchronized.

Shopify

Use Shopify's Admin API to fetch orders and map them to the required format. You'll need to create a custom app with read_orders and read_products scopes.

// Shopify order data extraction
const SHOPIFY_STORE = 'your-store.myshopify.com';
const ACCESS_TOKEN = process.env.SHOPIFY_ACCESS_TOKEN;
async function fetchShopifyOrders(sinceDate) {
const url = `https://${SHOPIFY_STORE}/admin/api/2024-01/orders.json?status=any&created_at_min=${sinceDate}&limit=250`;
const response = await fetch(url, {
headers: { 'X-Shopify-Access-Token': ACCESS_TOKEN }
});
const { orders } = await response.json();
return orders;
}
async function fetchProductDetails(productId) {
const url = `https://${SHOPIFY_STORE}/admin/api/2024-01/products/${productId}.json`;
const response = await fetch(url, {
headers: { 'X-Shopify-Access-Token': ACCESS_TOKEN }
});
const { product } = await response.json();
return product;
}
async function mapShopifyOrders(orders) {
const productCache = new Map();
const mappedOrders = [];
for (const order of orders) {
// Skip cancelled/refunded orders
if (order.cancelled_at || order.financial_status === 'refunded') continue;
const products = [];
for (const item of order.line_items) {
// Fetch product details for URL and image (with caching)
let product = productCache.get(item.product_id);
if (!product) {
product = await fetchProductDetails(item.product_id);
productCache.set(item.product_id, product);
}
products.push({
displayName: item.title,
productPath: `/products/${product?.handle || item.product_id}`,
category: item.vendor || product?.product_type || 'Uncategorized',
productCode: String(item.product_id),
sku: item.sku || String(item.variant_id),
thumbUrl: product?.image?.src || '',
purchasePrice: item.price,
quantity: item.quantity
});
}
if (products.length > 0) {
mappedOrders.push({
orderId: order.name, // e.g., "#1001"
orderDate: order.created_at,
orderValue: order.total_price,
currency: order.currency, // e.g., "USD", "EUR"
products
});
}
}
return mappedOrders;
}
đź’ˇ Shopify Tips
  • Use pagination (page_info) for stores with 250+ orders
  • Cache product details to avoid rate limits (40 requests/second)
  • Consider using GraphQL Bulk Operations for large historical exports

BigCommerce

BigCommerce provides order data through their V2/V3 APIs. Create an API account in your store's control panel under Settings → API Accounts with Orders and Products read permissions.

// BigCommerce order data extraction
const STORE_HASH = process.env.BC_STORE_HASH;
const ACCESS_TOKEN = process.env.BC_ACCESS_TOKEN;
async function fetchBigCommerceOrders(minDateCreated) {
const url = `https://api.bigcommerce.com/stores/${STORE_HASH}/v2/orders?min_date_created=${minDateCreated}&status_id=11`; // 11 = Completed
const response = await fetch(url, {
headers: {
'X-Auth-Token': ACCESS_TOKEN,
'Accept': 'application/json'
}
});
return response.json();
}
async function fetchOrderProducts(orderId) {
const url = `https://api.bigcommerce.com/stores/${STORE_HASH}/v2/orders/${orderId}/products`;
const response = await fetch(url, {
headers: {
'X-Auth-Token': ACCESS_TOKEN,
'Accept': 'application/json'
}
});
return response.json();
}
async function fetchProductDetails(productId) {
const url = `https://api.bigcommerce.com/stores/${STORE_HASH}/v3/catalog/products/${productId}?include=images`;
const response = await fetch(url, {
headers: {
'X-Auth-Token': ACCESS_TOKEN,
'Accept': 'application/json'
}
});
const { data } = await response.json();
return data;
}
async function mapBigCommerceOrders(orders) {
const productCache = new Map();
const mappedOrders = [];
for (const order of orders) {
const orderProducts = await fetchOrderProducts(order.id);
const products = [];
for (const item of orderProducts) {
let product = productCache.get(item.product_id);
if (!product) {
product = await fetchProductDetails(item.product_id);
productCache.set(item.product_id, product);
}
const thumbnail = product?.images?.find(img => img.is_thumbnail) || product?.images?.[0];
products.push({
displayName: item.name,
productPath: product?.custom_url?.url || `/products/${item.product_id}`,
category: product?.categories?.[0]?.toString() || 'Uncategorized',
productCode: String(item.product_id),
sku: item.sku,
thumbUrl: thumbnail?.url_thumbnail || '',
purchasePrice: String(item.base_price),
quantity: item.quantity
});
}
if (products.length > 0) {
mappedOrders.push({
orderId: String(order.id),
orderDate: new Date(order.date_created).toISOString(),
orderValue: String(order.total_inc_tax),
currency: order.currency_code, // e.g., "USD", "EUR"
products
});
}
}
return mappedOrders;
}
đź’ˇ BigCommerce Tips
  • Filter by status_id to include only completed orders
  • Fetch category names separately via the Categories API if needed
  • Use V3 API for products (includes images) and V2 for orders

Adobe Commerce (Magento 2)

Adobe Commerce exposes order data through its REST API. Generate an integration token in System → Integrations with access to Sales and Catalog resources.

// Adobe Commerce (Magento 2) order data extraction
const MAGENTO_URL = process.env.MAGENTO_BASE_URL;
const ACCESS_TOKEN = process.env.MAGENTO_ACCESS_TOKEN;
async function fetchMagentoOrders(fromDate) {
const searchCriteria = encodeURIComponent(
`searchCriteria[filter_groups][0][filters][0][field]=created_at&` +
`searchCriteria[filter_groups][0][filters][0][value]=${fromDate}&` +
`searchCriteria[filter_groups][0][filters][0][condition_type]=gteq&` +
`searchCriteria[filter_groups][1][filters][0][field]=status&` +
`searchCriteria[filter_groups][1][filters][0][value]=complete&` +
`searchCriteria[pageSize]=100`
);
const url = `${MAGENTO_URL}/rest/V1/orders?${searchCriteria}`;
const response = await fetch(url, {
headers: { 'Authorization': `Bearer ${ACCESS_TOKEN}` }
});
const { items } = await response.json();
return items;
}
async function fetchProductBySku(sku) {
const url = `${MAGENTO_URL}/rest/V1/products/${encodeURIComponent(sku)}`;
const response = await fetch(url, {
headers: { 'Authorization': `Bearer ${ACCESS_TOKEN}` }
});
return response.json();
}
async function fetchCategoryName(categoryId) {
const url = `${MAGENTO_URL}/rest/V1/categories/${categoryId}`;
const response = await fetch(url, {
headers: { 'Authorization': `Bearer ${ACCESS_TOKEN}` }
});
const category = await response.json();
return category.name;
}
async function mapMagentoOrders(orders) {
const productCache = new Map();
const categoryCache = new Map();
const mappedOrders = [];
for (const order of orders) {
const products = [];
// Filter to simple/configurable products only
const validItems = order.items.filter(item =>
['simple', 'configurable'].includes(item.product_type)
);
for (const item of validItems) {
let product = productCache.get(item.sku);
if (!product) {
product = await fetchProductBySku(item.sku);
productCache.set(item.sku, product);
}
// Get first category name
let categoryName = 'Uncategorized';
const categoryIds = product?.custom_attributes?.find(
attr => attr.attribute_code === 'category_ids'
)?.value;
if (categoryIds?.[0]) {
if (!categoryCache.has(categoryIds[0])) {
categoryCache.set(categoryIds[0], await fetchCategoryName(categoryIds[0]));
}
categoryName = categoryCache.get(categoryIds[0]);
}
// Build thumbnail URL
const thumbnail = product?.custom_attributes?.find(
attr => attr.attribute_code === 'thumbnail'
)?.value;
const thumbUrl = thumbnail
? `${MAGENTO_URL}/media/catalog/product${thumbnail}`
: '';
products.push({
displayName: item.name,
productPath: `/${product?.custom_attributes?.find(
attr => attr.attribute_code === 'url_key'
)?.value || item.sku}.html`,
category: categoryName,
productCode: String(item.product_id),
sku: item.sku,
thumbUrl,
purchasePrice: String(item.price),
quantity: item.qty_ordered
});
}
if (products.length > 0) {
mappedOrders.push({
orderId: order.increment_id,
orderDate: new Date(order.created_at).toISOString(),
orderValue: String(order.grand_total),
currency: order.order_currency_code, // e.g., "USD", "EUR"
products
});
}
}
return mappedOrders;
}
đź’ˇ Adobe Commerce Tips
  • Use search criteria to filter by date and order status
  • Product attributes like url_key and thumbnail are in custom_attributes
  • Consider async/batch processing for large catalogs
  • Media URLs follow the pattern: {base_url}/media/catalog/product{path}

Integration Best Practices

  • Rate Limiting: Add delays between API calls to respect platform rate limits. Use exponential backoff for retries.
  • Caching: Cache product details to minimize API calls—products rarely change between order syncs.
  • Incremental Sync: Track the last sync date and only fetch new orders since then, rather than the full history each time.
  • Error Handling: Log failed orders and retry them separately. Don't let one bad order block the entire sync.
  • Scheduling: Run syncs during off-peak hours to minimize impact on your store's performance.

Best Practices

  • Automate Capture: Implement the addOrder()call on your order confirmation page to continuously build your dataset
  • Quality Thumbnails: Use high-quality, consistently-sized square images (1:1 aspect ratio) for the best visual presentation
  • Standardize Categories: Use consistent, lowercase category names to improve recommendation grouping
  • Regular Maintenance: Schedule periodic storage reviews to clear old orders and maintain optimal performance
  • Test Integration: Test your addOrder()integration in a development environment before deploying to production