BigCommerce Integration
Blocker Outdoors uses BigCommerce for WordPress (Suma Fork v5.0.7.17), a custom version of the official BigCommerce WordPress plugin maintained by Rhino Group with enhancements for multi-storefront support and performance optimization.
Plugin Overview
Base Plugin: BigCommerce for WordPress
The official BigCommerce for WordPress plugin provides headless commerce integration:
- Official Version: Based on BigCommerce 5.0.x series
- Suma Fork: v5.0.7.17 with custom enhancements
- Repository: Private Rhino Group fork
- License: Proprietary (based on GPL v2)
- Minimum PHP: 8.1
- Minimum WordPress: 6.0
Suma Fork Enhancements
Key customizations in the Suma v5.0.7.17 fork:
-
Bi-Directional Sync Control: Granular control over data synchronization
- Choose which product fields sync from BC → WP
- Prevent WP edits from being overwritten
- Custom field mapping configuration
-
Pricing Nonce Bypass: Performance optimization for cached pages
- Skip nonce verification for pricing API calls
- Improved page load speed on high-traffic sites
- Maintains security with alternative validation
-
Multi-Storefront (MSF) Support: Enhanced channel management
- Channel-specific product visibility
- Per-channel pricing rules
- Channel-based inventory allocation
- Custom checkout URLs per channel
-
Advanced Import Features: Bulk operations and scheduling
- Category-based import filtering
- Scheduled import cron jobs
- Dry-run mode for testing
- Import progress tracking
-
Performance Optimizations: Database and API efficiency
- Optimized database queries for large catalogs
- API response caching
- Reduced webhook processing overhead
- Batch product updates
-
Custom Hooks & Filters: Extended functionality for developers
suma_bc_product_sync_fields- Customize synced fieldssuma_bc_import_batch_size- Adjust import batch sizesuma_bc_webhook_priority- Set webhook processing priority
Installation & Setup
Prerequisites
- WordPress 6.0+
- PHP 8.1+ with extensions: curl, json, mbstring
- BigCommerce store (any plan, Plus recommended for MSF)
- MySQL 5.7+ or MariaDB 10.6+
- 512MB+ PHP memory limit
- 60-second execution timeout for imports
BigCommerce Store Configuration
1. Create API Account
Navigate to Advanced Settings → API Accounts in BigCommerce admin:
API Account Name: WordPress - Blocker Outdoors Production
OAuth Scopes:
# Required 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
# Multi-Storefront scopes
- Channel Settings: Modify
- Channel Listings: Modify
- Sites & Routes: Modify
# Optional but recommended
- Store Inventory: Read-only
- Product Categories: Modify
- Product Brands: Modify
Save the API credentials securely:
- Client ID:
abc123xyz456 - Client Secret:
secret_key_here - Access Token:
access_token_here
2. Create WordPress Channel
In BigCommerce admin, go to Channel Manager → Create Channel:
Channel Type: Storefront
Platform: Custom
Channel Name: Blocker Outdoors - blockeroutdoors.com
Status: Active
Configuration:
- Site URL: https://blockeroutdoors.com
- Checkout URL: https://blockeroutdoors.com/checkout/
Note the Channel ID (visible in URL or API response) - required for WordPress configuration.
3. Configure Channel Settings
For the WordPress channel:
Product Visibility: Custom (select categories/products)
Pricing: Use channel-specific pricing rules
Inventory: Share or allocate separately
Checkout:
- Use embedded checkout
- Custom checkout domain: blockeroutdoors.com
- Enable cart recovery
Currency: USD
Default Language: English
WordPress Plugin Installation
Method 1: Manual Upload
# Download plugin from Rhino Group repository
# Upload to WordPress via admin or SFTP
# Via WP-CLI
wp plugin install /path/to/bigcommerce-suma-v5.0.7.17.zip --activate
# Or direct upload to wp-content/plugins/
unzip bigcommerce-suma-v5.0.7.17.zip -d /var/www/html/wp-content/plugins/
chown -R www-data:www-data /var/www/html/wp-content/plugins/bigcommerce
Method 2: Git Clone (Development)
cd /var/www/html/wp-content/plugins
git clone [email protected]:rhino-group/bigcommerce-wordpress-suma.git bigcommerce
cd bigcommerce
composer install --no-dev --optimize-autoloader
Configuration
Add Credentials to wp-config.php
/**
* BigCommerce API Credentials
* IMPORTANT: Never commit these to version control
*/
define( 'BIGCOMMERCE_CLIENT_ID', 'abc123xyz456' );
define( 'BIGCOMMERCE_CLIENT_SECRET', 'secret_key_here' );
define( 'BIGCOMMERCE_ACCESS_TOKEN', 'access_token_here' );
define( 'BIGCOMMERCE_CHANNEL_ID', 123456 ); // From Channel Manager
/**
* BigCommerce API Configuration
*/
define( 'BIGCOMMERCE_API_URL', 'https://api.bigcommerce.com' );
define( 'BIGCOMMERCE_STORE_URL', 'https://store-abc123.mybigcommerce.com' );
/**
* Import & Sync Settings
*/
define( 'BIGCOMMERCE_IMPORT_BATCH_SIZE', 50 ); // Products per batch
define( 'BIGCOMMERCE_CACHE_TTL', 900 ); // 15 minutes
define( 'BIGCOMMERCE_WEBHOOK_TIMEOUT', 30 ); // Webhook processing timeout
/**
* Suma Fork Specific Settings
*/
define( 'SUMA_BC_ENABLE_MSF', true ); // Multi-Storefront support
define( 'SUMA_BC_PRICING_NONCE_BYPASS', true ); // Performance optimization
define( 'SUMA_BC_SYNC_DIRECTION', 'bc_to_wp' ); // or 'bidirectional'
Plugin Settings (WordPress Admin)
Navigate to BigCommerce → Settings:
Account Tab:
- Verify API connection status
- Check channel configuration
- Test API connectivity
Import Tab:
Import Frequency: Daily at 3:00 AM
Import Batch Size: 50 products
Image Import: Yes (download to WordPress)
Category Import: Yes
Brand Import: Yes
Custom Fields: Import all
Cart & Checkout Tab:
Cart Type: Embedded (recommended)
Checkout URL: https://blockeroutdoors.com/checkout/{cart_id}
Cart Page: /cart/
Enable Abandoned Cart Recovery: Yes
Enable Guest Checkout: Yes
Channels Tab:
Active Channel: Blocker Outdoors (ID: 123456)
Channel-specific Pricing: Enabled
Product Sync Scope: Channel-specific only
Product Synchronization
Initial Product Import
Via WP-CLI (Recommended for Large Catalogs)
# Full import of all products
wp bigcommerce import products --all
# Import specific categories
wp bigcommerce import products --category=12,34,56
# Import by brand
wp bigcommerce import products --brand=89
# Import with verbose output
wp bigcommerce import products --all --verbose
# Dry run (preview without importing)
wp bigcommerce import products --all --dry-run
# Force reimport (refresh existing products)
wp bigcommerce import products --all --force
# Import in background (non-blocking)
wp bigcommerce import products --all --background
Import Process Overview:
1. Fetch product IDs from BigCommerce API
GET /stores/{store_hash}/v3/catalog/products?channel_id={channel_id}
2. For each product (in batches of 50):
a. Fetch product details
GET /stores/{store_hash}/v3/catalog/products/{id}?include=variants,images,custom_fields
b. Create/update WordPress post (bigcommerce_product)
c. Import product images to media library
d. Create/assign categories and brands
e. Store product meta (pricing, inventory, SKU)
f. Index for FacetWP and Algolia
3. Clean up orphaned products (deleted in BC)
4. Reindex search engines
Estimated Import Times:
- 100 products: ~2-3 minutes
- 500 products: ~10-15 minutes
- 1,000 products: ~20-30 minutes
- 5,000 products: ~2-3 hours
Via WordPress Admin
Navigate to BigCommerce → Settings → Import and click Start Import.
Import Status:
- View progress bar and current batch
- See logs for any errors
- Cancel import if needed
Real-Time Updates (Webhooks)
The plugin automatically registers webhooks with BigCommerce for instant updates.
Registered Webhooks
// Webhook endpoints (auto-registered on plugin activation)
$webhooks = [
// Product webhooks
[
'scope' => 'store/product/*',
'destination' => 'https://blockeroutdoors.com/wp-json/bigcommerce/v1/webhooks/product',
'is_active' => true,
],
// Inventory webhooks
[
'scope' => 'store/sku/inventory/updated',
'destination' => 'https://blockeroutdoors.com/wp-json/bigcommerce/v1/webhooks/inventory',
'is_active' => true,
],
// Order webhooks
[
'scope' => 'store/order/*',
'destination' => 'https://blockeroutdoors.com/wp-json/bigcommerce/v1/webhooks/order',
'is_active' => true,
],
];
Webhook Processing Flow
BigCommerce Event (e.g., product.updated)
│
│ POST https://blockeroutdoors.com/wp-json/bigcommerce/v1/webhooks/product
│ Headers:
│ X-BC-Webhook-Signature: sha256=...
│ Content-Type: application/json
│ Payload:
│ { "scope": "store/product/updated", "data": { "id": 12345 } }
│
▼
WordPress REST API Endpoint
│
│ (1) Verify HMAC signature
│ $signature = $_SERVER['HTTP_X_BC_WEBHOOK_SIGNATURE'];
│ verify_webhook_signature( $payload, $signature );
│
├──► [FAIL] Return 401 Unauthorized
│
├──► [PASS] Continue
│
▼
Add to Sync Queue
│
│ (2) Store product ID in wp_options transient
│ $queue = get_transient( 'bc_sync_queue' ) ?: [];
│ $queue[] = $product_id;
│ set_transient( 'bc_sync_queue', $queue, 3600 );
│
│ (3) Return 200 OK immediately (non-blocking)
│
▼
Background Processing (wp_cron)
│
│ (4) Cron job runs every 5 minutes
│ wp_schedule_event( time(), 'every_5_minutes', 'bc_process_sync_queue' );
│
▼
Fetch Product from BigCommerce API
│
│ (5) GET /stores/{store_hash}/v3/catalog/products/{id}
│
▼
Update WordPress Product Post
│
│ (6) Update post content, title, meta
│ (7) Update pricing, inventory status
│ (8) Sync product images
│ (9) Update categories and tags
│
▼
Clear Caches & Reindex
│
│ (10) Purge page cache (WP Rocket, Cloudflare)
│ (11) Reindex FacetWP
│ (12) Update Algolia search index
│ (13) Clear object cache (Redis/Memcached)
│
▼
Sync Complete
│
│ Log success or errors
Webhook Security (HMAC Verification)
/**
* Verify BigCommerce webhook signature
*/
function verify_bigcommerce_webhook( $payload, $signature_header ) {
// Extract signature from header
// Format: sha256=abc123...
if ( ! preg_match( '/^sha256=(.+)$/', $signature_header, $matches ) ) {
return false;
}
$received_signature = $matches[1];
// Calculate expected signature
$secret = BIGCOMMERCE_CLIENT_SECRET;
$expected_signature = hash_hmac( 'sha256', $payload, $secret );
// Timing-safe comparison
return hash_equals( $expected_signature, $received_signature );
}
// Usage in webhook endpoint
add_action( 'rest_api_init', function() {
register_rest_route( 'bigcommerce/v1', '/webhooks/product', [
'methods' => 'POST',
'callback' => 'handle_product_webhook',
'permission_callback' => '__return_true', // Signature verified in callback
] );
} );
function handle_product_webhook( WP_REST_Request $request ) {
$payload = $request->get_body();
$signature = $request->get_header( 'X-BC-Webhook-Signature' );
if ( ! verify_bigcommerce_webhook( $payload, $signature ) ) {
return new WP_Error(
'invalid_signature',
'Webhook signature verification failed',
[ 'status' => 401 ]
);
}
// Process webhook...
$data = json_decode( $payload, true );
$product_id = $data['data']['id'];
// Add to sync queue
add_product_to_sync_queue( $product_id );
return [ 'success' => true ];
}
Scheduled Synchronization
Daily full reconciliation cron job:
// wp-content/mu-plugins/blocker-bc-cron.php
<?php
/**
* Daily BigCommerce product reconciliation
* Runs at 3:00 AM daily to ensure data consistency
*/
add_action( 'bigcommerce_daily_sync', 'blocker_sync_all_products' );
if ( ! wp_next_scheduled( 'bigcommerce_daily_sync' ) ) {
wp_schedule_event( strtotime( '03:00:00' ), 'daily', 'bigcommerce_daily_sync' );
}
function blocker_sync_all_products() {
$start_time = microtime( true );
$synced = 0;
$errors = 0;
// Fetch all BC product IDs for channel
$bc_product_ids = get_bigcommerce_product_ids_for_channel( BIGCOMMERCE_CHANNEL_ID );
// Get all WordPress product IDs
$wp_products = get_posts( [
'post_type' => 'bigcommerce_product',
'posts_per_page' => -1,
'fields' => 'ids',
'post_status' => [ 'publish', 'draft' ],
] );
// Sync each product
foreach ( $bc_product_ids as $bc_id ) {
try {
sync_bigcommerce_product( $bc_id );
$synced++;
} catch ( Exception $e ) {
error_log( "BC Sync Error for product $bc_id: " . $e->getMessage() );
$errors++;
}
// Rate limiting: 150 requests per 30 seconds
if ( $synced % 100 === 0 ) {
sleep( 30 );
}
}
// Delete orphaned WordPress products (deleted in BC)
$wp_bc_ids = array_map( function( $wp_id ) {
return get_post_meta( $wp_id, 'bigcommerce_id', true );
}, $wp_products );
$orphaned = array_diff( $wp_bc_ids, $bc_product_ids );
foreach ( $orphaned as $wp_id ) {
wp_delete_post( $wp_id, true );
}
// Reindex search
do_action( 'facetwp_index_all' );
do_action( 'algolia_reindex_all' );
$duration = microtime( true ) - $start_time;
// Log results
error_log( sprintf(
'BigCommerce Daily Sync Complete: %d synced, %d errors, %d deleted, %.2f seconds',
$synced,
$errors,
count( $orphaned ),
$duration
) );
// Send notification email on errors
if ( $errors > 10 ) {
wp_mail(
'[email protected]',
'Blocker Outdoors: BC Sync Errors',
"Daily sync completed with $errors errors. Check logs for details."
);
}
}
Cart & Checkout Integration
Embedded Checkout
Blocker Outdoors uses BigCommerce embedded checkout for seamless user experience.
Configuration
// Checkout URL pattern
$checkout_url = sprintf(
'https://blockeroutdoors.com/checkout/%s',
$cart_id
);
// Redirect to checkout
wp_redirect( $checkout_url );
exit;
Checkout Customization
BigCommerce checkout can be customized via Checkout SDK and Script Manager:
<!-- Add custom CSS to BigCommerce checkout -->
<style>
/* Match Blocker Outdoors branding */
.checkout-header {
background-color: #2c5f2d;
}
.checkout-button--primary {
background-color: #97c93d;
border-color: #97c93d;
}
</style>
<script>
// Track checkout steps
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
'event': 'checkout_start',
'ecommerce': {
'checkout': {
'actionField': {'step': 1},
'products': [{...}]
}
}
});
</script>
Cart API Integration
// Add to cart via REST API
async function addToCart(productId, variantId, quantity = 1) {
const response = await fetch('/wp-json/bigcommerce/v3/carts', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
line_items: [{
product_id: productId,
variant_id: variantId,
quantity: quantity
}]
})
});
const data = await response.json();
// Store cart ID in cookie
document.cookie = `bigcommerce_cart_id=${data.id}; path=/; max-age=2592000`;
// Update cart widget
updateCartWidget(data);
// Track event
window.dataLayer.push({
'event': 'add_to_cart',
'ecommerce': {
'items': [{
'item_id': productId,
'item_name': data.line_items.physical_items[0].name,
'price': data.line_items.physical_items[0].sale_price,
'quantity': quantity
}]
}
});
return data;
}
Troubleshooting
Common Issues
Issue: Products not importing
# Check API connectivity
wp bigcommerce test-connection
# Check import queue
wp bigcommerce queue-status
# Re-register webhooks
wp bigcommerce webhooks-register --force
# Clear cache and retry
wp cache flush
wp bigcommerce import products --all --force
Issue: Webhook verification failing
// Debug webhook signatures
add_filter( 'bigcommerce_webhook_verify', function( $verified, $payload, $signature ) {
if ( ! $verified ) {
error_log( 'Webhook verification failed' );
error_log( 'Payload: ' . $payload );
error_log( 'Signature: ' . $signature );
error_log( 'Expected: ' . hash_hmac( 'sha256', $payload, BIGCOMMERCE_CLIENT_SECRET ) );
}
return $verified;
}, 10, 3 );
Issue: Product images not loading
# Regenerate thumbnails
wp media regenerate --yes
# Re-download BC images
wp bigcommerce sync-images --all
Debug Mode
Enable debug logging:
// wp-config.php
define( 'BIGCOMMERCE_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
// Check logs
tail -f /var/www/html/wp-content/debug.log
API Rate Limits
BigCommerce API rate limits:
- Standard Plans: 150 requests per 30 seconds
- Plus/Enterprise: 450 requests per 30 seconds
Rate Limit Handling:
function bigcommerce_api_request_with_retry( $endpoint, $method = 'GET', $data = [] ) {
$max_retries = 3;
$retry_count = 0;
while ( $retry_count < $max_retries ) {
$response = wp_remote_request( $endpoint, [
'method' => $method,
'headers' => [
'X-Auth-Token' => BIGCOMMERCE_ACCESS_TOKEN,
'Content-Type' => 'application/json',
],
'body' => json_encode( $data ),
] );
// Check for rate limit (429 status)
if ( wp_remote_retrieve_response_code( $response ) === 429 ) {
$retry_after = wp_remote_retrieve_header( $response, 'X-Rate-Limit-Time-Reset-Ms' );
$sleep_ms = $retry_after ?: 30000; // Default 30 seconds
error_log( "Rate limit hit. Sleeping for {$sleep_ms}ms" );
usleep( $sleep_ms * 1000 );
$retry_count++;
continue;
}
return $response;
}
return new WP_Error( 'rate_limit_exceeded', 'Max retries reached' );
}