BigCommerce Integration
Muddy uses BigCommerce for WordPress (Suma Fork v5.0.7.10), a custom version of the official BigCommerce WordPress plugin maintained by Rhino Group with enhancements for GSM Outdoors brands.
Plugin Overview
Base Plugin: BigCommerce for WordPress
The official BigCommerce for WordPress plugin provides headless commerce integration:
- Official Version: Based on 5.0.x series
- Suma Fork: v5.0.7.10 with custom enhancements
- Repository: Private Rhino Group fork
- License: Proprietary (based on GPL v2)
Suma Fork Enhancements
Key customizations in the Suma fork:
- Bi-Directional Sync Control: Granular control over what data syncs between platforms
- Pricing Nonce Bypass: Performance optimization for high-traffic scenarios
- Advanced Import Features: Bulk import tools and scheduling
- HuntStand Integration Hooks: Custom hooks for cross-platform functionality
- Promo Flag Support: Integration with custom promotional messaging system
- Performance Optimizations: Database query optimization, caching improvements
Installation & Setup
Prerequisites
- WordPress 6.0+
- PHP 8.1+
- BigCommerce store (any plan)
- MySQL 5.7+ or MariaDB 10.3+
BigCommerce Store Configuration
1. Create API Account
Navigate to Advanced Settings → API Accounts in BigCommerce admin:
API Account Name: WordPress - Muddy Production
OAuth Scopes:
- Carts: Modify
- Checkout Content: Modify
- Customers: Modify
- Customer Login: Login
- Information & Settings: Read-only
- Marketing: Modify
- Orders: Modify
- Order Transactions: Read-only
- Products: Modify
- Themes: Read-only
- Channel Settings: Modify
- Channel Listings: Modify
- Sites & Routes: Modify
2. Create WordPress Channel
In BigCommerce admin, go to Channel Manager:
Channel Type: WordPress
Channel Name: Muddy - gomuddy.com
Status: Active
Domain: gomuddy.com
Note: The channel ID will be used in WordPress configuration.
WordPress Plugin Installation
Manual Installation
# Upload plugin to WordPress
wp plugin install /path/to/bigcommerce-suma-v5.0.7.10.zip --activate
# Or via git (private repo access required)
cd wp-content/plugins
git clone [email protected]:rhino-group/bigcommerce-wordpress-suma.git bigcommerce
cd bigcommerce
composer install --no-dev
Configuration
Add BigCommerce credentials to wp-config.php:
// BigCommerce API Credentials
define( 'BIGCOMMERCE_CLIENT_ID', 'your_client_id' );
define( 'BIGCOMMERCE_CLIENT_SECRET', 'your_client_secret' );
define( 'BIGCOMMERCE_ACCESS_TOKEN', 'your_access_token' );
define( 'BIGCOMMERCE_CHANNEL_ID', 123456 );
// Optional: Custom configuration
define( 'BIGCOMMERCE_API_URL', 'https://api.bigcommerce.com' );
define( 'BIGCOMMERCE_IMPORT_BATCH_SIZE', 50 );
define( 'BIGCOMMERCE_CACHE_TTL', 900 ); // 15 minutes
Product Synchronization
Initial Product Import
Via WP-CLI (Recommended)
# Import all products
wp bigcommerce import products --all
# Import specific categories
wp bigcommerce import products --category=12,34,56
# Import with progress output
wp bigcommerce import products --all --verbose
# Dry run (preview import)
wp bigcommerce import products --all --dry-run
Via WordPress Admin
Navigate to BigCommerce → Settings → Import and click Import Products.
Import Process:
- Fetches product data from BigCommerce API
- Creates WordPress custom post type
bigcommerce_product - Imports product images to WordPress media library
- Creates product categories and tags
- Indexes products for search (Algolia, FacetWP)
Import Duration: ~5-10 minutes for 500 products
Incremental Updates (Webhooks)
The plugin registers webhooks with BigCommerce for real-time updates:
// Registered webhook endpoints
/wp-json/bigcommerce/v1/webhooks/product-update
/wp-json/bigcommerce/v1/webhooks/product-delete
/wp-json/bigcommerce/v1/webhooks/inventory-update
/wp-json/bigcommerce/v1/webhooks/order-created
Webhook Flow:
BigCommerce Event (e.g., product updated)
│
│ POST request with HMAC signature
│
▼
WordPress Webhook Endpoint
│
│ Verify HMAC signature
│
▼
Add to Import Queue
│
│ Background processing (cron)
│
▼
Update WordPress Product
│
│ Update post meta, taxonomies
│
▼
Clear Caches & Reindex
Webhook Security:
// Verify webhook signature
function verify_bigcommerce_webhook( $payload, $signature ) {
$secret = BIGCOMMERCE_CLIENT_SECRET;
$calculated = base64_encode( hash_hmac( 'sha256', $payload, $secret, true ) );
return hash_equals( $calculated, $signature );
}
Scheduled Synchronization
Daily cron job for full reconciliation:
// wp-content/mu-plugins/bigcommerce-cron.php
add_action( 'bigcommerce_daily_sync', 'muddy_sync_all_products' );
function muddy_sync_all_products() {
// Fetch all product IDs from BigCommerce
$bc_products = get_bigcommerce_product_ids();
// Get WordPress product IDs
$wp_products = get_wordpress_bigcommerce_ids();
// Find products to update
$to_update = array_intersect( $bc_products, $wp_products );
// Find products to delete (removed from BC)
$to_delete = array_diff( $wp_products, $bc_products );
// Queue updates
foreach ( $to_update as $product_id ) {
BigCommerce\Import\Import_Queue::add_product( $product_id );
}
// Delete removed products
foreach ( $to_delete as $product_id ) {
wp_delete_post( $product_id, true );
}
}
// Schedule the cron job
if ( ! wp_next_scheduled( 'bigcommerce_daily_sync' ) ) {
wp_schedule_event( strtotime( '3:00 AM' ), 'daily', 'bigcommerce_daily_sync' );
}
Cart & Checkout
Cart Management
Cart operations use BigCommerce's Cart API with WordPress as a proxy.
Add to Cart:
// Frontend JavaScript (simplified)
jQuery('.buy-button').on('click', function(e) {
e.preventDefault();
const productId = $(this).data('product-id');
const variantId = $(this).data('variant-id');
const quantity = $('#quantity').val();
$.ajax({
url: muddy_cart.ajax_url,
method: 'POST',
data: {
action: 'bigcommerce_add_to_cart',
product_id: productId,
variant_id: variantId,
quantity: quantity,
nonce: muddy_cart.nonce
},
success: function(response) {
if (response.success) {
// Update cart count
$('.cart-count').text(response.data.item_count);
// Show success message
showNotification('Product added to cart');
}
}
});
});
PHP Handler:
add_action( 'wp_ajax_bigcommerce_add_to_cart', 'muddy_ajax_add_to_cart' );
add_action( 'wp_ajax_nopriv_bigcommerce_add_to_cart', 'muddy_ajax_add_to_cart' );
function muddy_ajax_add_to_cart() {
check_ajax_referer( 'bigcommerce_cart_nonce', 'nonce' );
$product_id = intval( $_POST['product_id'] );
$variant_id = intval( $_POST['variant_id'] );
$quantity = intval( $_POST['quantity'] );
// Get or create cart
$cart = BigCommerce\Cart\Cart::get_cart();
// Add item to cart via BC API
$result = $cart->add_item( $product_id, $variant_id, $quantity );
if ( is_wp_error( $result ) ) {
wp_send_json_error( $result->get_error_message() );
}
wp_send_json_success( [
'item_count' => $cart->get_item_count(),
'subtotal' => $cart->get_subtotal(),
'cart_url' => get_permalink( get_option( 'bigcommerce_cart_page_id' ) )
] );
}
Cart Page
WordPress template displays cart contents fetched from BigCommerce:
// templates/cart/cart.php (simplified)
$cart = BigCommerce\Cart\Cart::get_cart();
$items = $cart->get_items();
if ( empty( $items ) ) {
echo '<p>Your cart is empty.</p>';
return;
}
foreach ( $items as $item ) :
?>
<div class="cart-item" data-item-id="<?php echo esc_attr( $item['id'] ); ?>">
<img src="<?php echo esc_url( $item['image_url'] ); ?>" alt="">
<h3><?php echo esc_html( $item['name'] ); ?></h3>
<span class="price"><?php echo esc_html( $item['sale_price'] ?: $item['list_price'] ); ?></span>
<input type="number" class="quantity" value="<?php echo esc_attr( $item['quantity'] ); ?>" min="1">
<button class="remove-item">Remove</button>
</div>
<?php
endforeach;
echo '<div class="cart-total">Total: ' . esc_html( $cart->get_total() ) . '</div>';
echo '<a href="' . esc_url( $cart->get_checkout_url() ) . '" class="checkout-button">Checkout</a>';
Checkout Flow
Redirect to BigCommerce:
// When customer clicks "Checkout", redirect to BC hosted checkout
function get_checkout_url() {
$cart = BigCommerce\Cart\Cart::get_cart();
$cart_id = $cart->get_cart_id();
// Generate checkout URL
$channel_id = BIGCOMMERCE_CHANNEL_ID;
$checkout_url = "https://store-{hash}.mybigcommerce.com/checkout/{$cart_id}";
// Optional: Add embedded checkout
// $checkout_url = "https://gomuddy.com/checkout?cart_id={$cart_id}";
return $checkout_url;
}
Post-Checkout Redirect:
Configure in BigCommerce admin (Channel Manager → WordPress → Settings):
Checkout Return URL: https://gomuddy.com/thank-you
Order Status Page URL: https://gomuddy.com/account/orders
HuntStand Integration
Custom integration for cross-platform product recommendations between Muddy website and HuntStand mobile app.
API Endpoint
// wp-content/plugins/bigcommerce-suma/includes/huntstand-api.php
add_action( 'rest_api_init', function() {
register_rest_route( 'huntstand/v1', '/products', [
'methods' => 'GET',
'callback' => 'muddy_huntstand_products',
'permission_callback' => 'muddy_huntstand_authenticate'
] );
} );
function muddy_huntstand_authenticate( $request ) {
$auth_header = $request->get_header( 'Authorization' );
if ( empty( $auth_header ) ) {
return new WP_Error( 'missing_auth', 'Authorization header required', [ 'status' => 401 ] );
}
// Verify Bearer token
$token = str_replace( 'Bearer ', '', $auth_header );
$valid = verify_huntstand_token( $token );
return $valid;
}
function muddy_huntstand_products( $request ) {
$category = $request->get_param( 'category' );
$limit = $request->get_param( 'limit' ) ?: 20;
// Query BigCommerce products
$args = [
'post_type' => 'bigcommerce_product',
'posts_per_page' => $limit,
'meta_query' => [
[
'key' => 'bigcommerce_inventory',
'value' => 0,
'compare' => '>'
]
]
];
if ( $category ) {
$args['tax_query'] = [
[
'taxonomy' => 'bigcommerce_category',
'field' => 'slug',
'terms' => $category
]
];
}
$products = get_posts( $args );
$response = [];
foreach ( $products as $product ) {
$bc_id = get_post_meta( $product->ID, 'bigcommerce_id', true );
$price = get_post_meta( $product->ID, 'bigcommerce_price', true );
$sale_price = get_post_meta( $product->ID, 'bigcommerce_sale_price', true );
$inventory = get_post_meta( $product->ID, 'bigcommerce_inventory', true );
$sku = get_post_meta( $product->ID, 'bigcommerce_sku', true );
$response[] = [
'id' => $bc_id,
'name' => $product->post_title,
'description' => wp_trim_words( $product->post_content, 50 ),
'sku' => $sku,
'price' => (float) $price,
'sale_price' => $sale_price ? (float) $sale_price : null,
'inventory' => (int) $inventory,
'category' => get_primary_category( $product->ID ),
'image_url' => get_the_post_thumbnail_url( $product->ID, 'large' ),
'url' => get_permalink( $product->ID )
];
}
return rest_ensure_response( $response );
}
Authentication
OAuth 2.0 token exchange:
// HuntStand service generates access token
// Token stored in wp_options for verification
function verify_huntstand_token( $token ) {
$stored_token = get_option( 'huntstand_api_token' );
$expiry = get_option( 'huntstand_token_expiry' );
if ( $token !== $stored_token ) {
return false;
}
if ( time() > $expiry ) {
return false; // Token expired
}
return true;
}
Promo Flags
Custom promotional messaging system integrated with BigCommerce products.
Data Structure
// Custom post type: promo_flag
register_post_type( 'promo_flag', [
'labels' => [
'name' => 'Promo Flags',
'singular_name' => 'Promo Flag'
],
'public' => false,
'show_ui' => true,
'supports' => [ 'title' ],
'menu_icon' => 'dashicons-flag'
] );
// Meta fields
$promo_meta = [
'flag_type' => 'sale|new|exclusive|featured',
'message' => 'Free Shipping!',
'product_ids' => [ 123, 456, 789 ], // BigCommerce product IDs
'priority' => 10,
'start_date' => '2026-04-01',
'end_date' => '2026-04-30'
];
Display Logic
// Get active promo flags for product
function get_product_promo_flags( $bigcommerce_id ) {
$now = current_time( 'timestamp' );
$args = [
'post_type' => 'promo_flag',
'posts_per_page' => -1,
'meta_query' => [
[
'key' => 'product_ids',
'value' => sprintf( ':"%d";', $bigcommerce_id ),
'compare' => 'LIKE'
],
[
'key' => 'start_date',
'value' => $now,
'compare' => '<=',
'type' => 'NUMERIC'
],
[
'key' => 'end_date',
'value' => $now,
'compare' => '>=',
'type' => 'NUMERIC'
]
],
'orderby' => 'meta_value_num',
'meta_key' => 'priority',
'order' => 'DESC'
];
return get_posts( $args );
}
// Display on product page
add_action( 'bigcommerce/template/product/before_title', 'muddy_display_promo_flag' );
function muddy_display_promo_flag() {
global $post;
$bc_id = get_post_meta( $post->ID, 'bigcommerce_id', true );
$flags = get_product_promo_flags( $bc_id );
if ( empty( $flags ) ) {
return;
}
$flag = $flags[0]; // Highest priority
$type = get_post_meta( $flag->ID, 'flag_type', true );
$message = get_post_meta( $flag->ID, 'message', true );
printf(
'<div class="promo-flag promo-flag--%s">%s</div>',
esc_attr( $type ),
esc_html( $message )
);
}
CSS Styling
.promo-flag {
display: inline-block;
padding: 0.5rem 1rem;
border-radius: 4px;
font-weight: 600;
font-size: 0.875rem;
text-transform: uppercase;
margin-bottom: 1rem;
}
.promo-flag--sale {
background-color: #ef4444;
color: white;
}
.promo-flag--new {
background-color: #3b82f6;
color: white;
}
.promo-flag--exclusive {
background-color: #8b5cf6;
color: white;
}
.promo-flag--featured {
background-color: #f59e0b;
color: white;
}
Performance Optimization
API Response Caching
// Cache BigCommerce API responses
function muddy_get_bc_product( $product_id ) {
$cache_key = 'bc_product_' . $product_id;
$cached = wp_cache_get( $cache_key, 'bigcommerce' );
if ( false !== $cached ) {
return $cached;
}
// Fetch from API
$product = BigCommerce\Api\Products::get_product( $product_id );
// Cache for 15 minutes
wp_cache_set( $cache_key, $product, 'bigcommerce', 15 * MINUTE_IN_SECONDS );
return $product;
}
Database Query Optimization
// Index for fast BigCommerce ID lookups
global $wpdb;
$wpdb->query( "
CREATE INDEX idx_bc_id ON {$wpdb->postmeta}(meta_key, meta_value(50))
WHERE meta_key = 'bigcommerce_id'
" );
Pricing Nonce Bypass
Suma fork optimization that bypasses nonce verification for pricing updates in high-traffic scenarios:
// wp-content/plugins/bigcommerce-suma/includes/pricing-nonce-bypass.php
// CAUTION: Only enable if you understand the security implications
define( 'BIGCOMMERCE_BYPASS_PRICING_NONCE', true );
add_filter( 'bigcommerce/pricing/verify_nonce', function( $verify ) {
if ( defined( 'BIGCOMMERCE_BYPASS_PRICING_NONCE' ) && BIGCOMMERCE_BYPASS_PRICING_NONCE ) {
// Skip nonce verification for pricing AJAX requests
// This improves performance but reduces CSRF protection
return false; // Don't verify
}
return $verify;
} );
Security Note: This optimization should only be used on high-traffic sites where nonce verification causes performance bottlenecks. Ensure proper security measures are in place (rate limiting, IP whitelisting, etc.).
Troubleshooting
Common Issues
Products not importing:
# Check import queue
wp bigcommerce queue status
# Clear and restart import
wp bigcommerce queue clear
wp bigcommerce import products --all
Webhook failures:
# Check webhook logs
wp bigcommerce webhooks list
# Re-register webhooks
wp bigcommerce webhooks register
Cart issues:
# Clear cart cache
wp cache flush
wp transient delete --all
# Test cart API connection
wp bigcommerce test cart-api
Debug Mode
Enable debug logging:
// wp-config.php
define( 'BIGCOMMERCE_DEBUG', true );
define( 'BIGCOMMERCE_LOG_FILE', WP_CONTENT_DIR . '/bigcommerce-debug.log' );
View logs:
tail -f wp-content/bigcommerce-debug.log