Custom Plugins
Muddy uses a suite of custom WordPress plugins developed by Rhino Group (Suma) for GSM Outdoors brands. These plugins provide e-commerce functionality, marketing integrations, and site-specific features.
Suma Patches v1.5.21
WordPress core customizations and enhancements for performance, security, and e-commerce functionality.
Purpose
Suma Patches applies targeted modifications to WordPress core, WooCommerce, and popular plugins without modifying core files directly. Changes are applied via hooks and filters.
Key Features
Performance Optimizations
// Disable unnecessary WordPress features
remove_action( 'wp_head', 'wp_generator' );
remove_action( 'wp_head', 'wlwmanifest_link' );
remove_action( 'wp_head', 'rsd_link' );
remove_action( 'wp_head', 'wp_shortlink_wp_head' );
// Defer JavaScript loading
add_filter( 'script_loader_tag', function( $tag, $handle ) {
$defer_scripts = [ 'jquery', 'jquery-migrate', 'wp-embed' ];
if ( in_array( $handle, $defer_scripts, true ) ) {
return str_replace( ' src', ' defer src', $tag );
}
return $tag;
}, 10, 2 );
// Optimize database queries
add_action( 'init', function() {
global $wpdb;
$wpdb->query( "SET SESSION query_cache_type = ON" );
} );
Security Enhancements
// Remove WordPress version from RSS feeds
add_filter( 'the_generator', '__return_empty_string' );
// Disable XML-RPC
add_filter( 'xmlrpc_enabled', '__return_false' );
// Add security headers
add_action( 'send_headers', function() {
header( 'X-Frame-Options: SAMEORIGIN' );
header( 'X-Content-Type-Options: nosniff' );
header( 'X-XSS-Protection: 1; mode=block' );
header( 'Referrer-Policy: strict-origin-when-cross-origin' );
} );
BigCommerce Integration Patches
// Fix BigCommerce product sync issues
add_filter( 'bigcommerce/import/product/data', function( $data, $product_id ) {
// Ensure consistent SKU format
if ( isset( $data['sku'] ) ) {
$data['sku'] = strtoupper( trim( $data['sku'] ) );
}
// Handle missing inventory
if ( ! isset( $data['inventory'] ) || $data['inventory'] === '' ) {
$data['inventory'] = 0;
}
return $data;
}, 10, 2 );
// Fix cart pricing calculations
add_filter( 'bigcommerce/cart/item/price', function( $price, $item ) {
// Apply tax calculations consistently
$tax_rate = get_option( 'muddy_tax_rate', 0.07 );
return $price * ( 1 + $tax_rate );
}, 10, 2 );
Admin Customizations
// Custom admin dashboard widgets
add_action( 'wp_dashboard_setup', function() {
wp_add_dashboard_widget(
'muddy_sales_stats',
'Sales Statistics',
'muddy_render_sales_dashboard_widget'
);
} );
// Simplify admin menu
add_action( 'admin_menu', function() {
remove_menu_page( 'edit-comments.php' );
remove_menu_page( 'tools.php' );
}, 999 );
Installation
wp plugin install /path/to/suma-patches-v1.5.21.zip --activate
Configuration
No configuration required. Patches are applied automatically upon activation.
Suma Dealer Locator v3.0.2
Store finder with Google Maps integration, GeoIP lookup, and advanced filtering.
Features
- Google Maps Integration: Interactive map with custom markers
- GeoIP Detection: Automatic user location detection
- Radius Search: Find dealers within specified distance
- Category Filtering: Filter by dealer type, services offered
- Elementor Widget: Drag-and-drop dealer locator widget
- Shortcode Support:
[suma_dealer_locator]
Installation & Setup
wp plugin install /path/to/suma-dealer-locator-v3.0.2.zip --activate
Configuration:
Navigate to Settings → Dealer Locator and configure:
Google Maps API Key: AIza...
Default Zoom Level: 10
Search Radius Options: 10, 25, 50, 100 miles
Enable GeoIP: Yes
Map Style: Custom (JSON)
Adding Dealers
Dealers are stored as a custom post type dealer:
// Programmatically add a dealer
wp_insert_post( [
'post_type' => 'dealer',
'post_title' => 'Muddy Pro Shop - Dallas',
'post_status' => 'publish',
'meta_input' => [
'dealer_address' => '123 Main St, Dallas, TX 75201',
'dealer_phone' => '(555) 123-4567',
'dealer_email' => '[email protected]',
'dealer_website' => 'https://dallas.muddyproshop.com',
'dealer_latitude' => 32.7767,
'dealer_longitude' => -96.7970,
'dealer_category' => [ 'retail', 'service' ]
]
] );
Elementor Widget Usage
- Edit page with Elementor
- Search for "Dealer Locator" widget
- Drag onto page
- Configure options:
Map Height: 500px
Show Search Box: Yes
Default Location: Dallas, TX
Radius Options: 10, 25, 50, 100
Filter by Category: Yes
Customization
// Custom marker icon
add_filter( 'suma_dealer_locator_marker_icon', function( $icon_url ) {
return get_stylesheet_directory_uri() . '/assets/images/dealer-marker.png';
} );
// Custom info window content
add_filter( 'suma_dealer_locator_info_window', function( $content, $dealer_id ) {
$phone = get_post_meta( $dealer_id, 'dealer_phone', true );
$website = get_post_meta( $dealer_id, 'dealer_website', true );
return sprintf(
'<div class="dealer-info">
<h3>%s</h3>
<p>%s</p>
<p><a href="tel:%s">%s</a></p>
<p><a href="%s" target="_blank">Visit Website</a></p>
</div>',
get_the_title( $dealer_id ),
get_post_meta( $dealer_id, 'dealer_address', true ),
esc_attr( $phone ),
esc_html( $phone ),
esc_url( $website )
);
}, 10, 2 );
Suma Analytics v1.3.4
E-commerce event tracking for BigCommerce with GA4 integration.
Tracked Events
product/viewed- Product detail page viewproduct/clicked- Product link clickproduct/added-to-cart- Add to cartcart/viewed- Cart page viewcheckout/viewed- Checkout initiationcheckout/complete- Purchase complete
Installation
wp plugin install /path/to/suma-analytics-v1.3.4.zip --activate
Configuration:
// wp-config.php
define( 'SUMA_ANALYTICS_GA4_ID', 'G-XXXXXXXXXX' );
define( 'SUMA_ANALYTICS_GTM_ID', 'GTM-XXXXXXX' );
Implementation
Analytics events are automatically tracked via JavaScript:
// Automatic tracking
document.addEventListener('DOMContentLoaded', () => {
// Track product clicks
document.querySelectorAll('.product-card a').forEach(link => {
link.addEventListener('click', (e) => {
const productId = e.target.closest('.product-card').dataset.productId;
sumaAnalytics.trackEvent('product/clicked', { product_id: productId });
});
});
// Track add to cart
document.querySelectorAll('.add-to-cart-button').forEach(button => {
button.addEventListener('click', (e) => {
const productId = e.target.dataset.productId;
const price = e.target.dataset.price;
sumaAnalytics.trackEvent('product/added-to-cart', {
product_id: productId,
price: price,
quantity: 1
});
});
});
});
Custom Event Tracking
// Track custom event from PHP
do_action( 'suma_analytics_track_event', 'custom/event', [
'category' => 'engagement',
'action' => 'video_play',
'label' => 'Product Demo Video',
'value' => 1
] );
Suma BazaarVoice Integrator v1.1.4
Product review integration with automated XML feed generation and variant support.
Features
- Automated product feed generation
- Variant-level reviews
- UPC/GTIN handling
- Scheduled updates via cron
- Category mapping
- Image synchronization
Installation
wp plugin install /path/to/suma-bazaarvoice-integrator-v1.1.4.zip --activate
Configuration:
Navigate to Settings → BazaarVoice and configure:
Client Name: muddy
API Key: [your_api_key]
Feed URL: https://gomuddy.com/bazaarvoice-feed.xml
Update Frequency: Daily at 2:00 AM
Include Out of Stock: No
Feed Generation
// Generate feed manually
do_action( 'suma_bazaarvoice_generate_feed' );
// Scheduled via WP-Cron
if ( ! wp_next_scheduled( 'suma_bazaarvoice_daily_feed' ) ) {
wp_schedule_event( strtotime( '2:00 AM' ), 'daily', 'suma_bazaarvoice_daily_feed' );
}
add_action( 'suma_bazaarvoice_daily_feed', function() {
$generator = new Suma_BazaarVoice_Feed_Generator();
$generator->generate_product_feed();
} );
Product Feed Format
<?xml version="1.0" encoding="UTF-8"?>
<Feed xmlns="http://www.bazaarvoice.com/xs/PRR/ProductFeed/14.6">
<Products>
<Product>
<ExternalId>12345</ExternalId>
<Name>Apex Hang-On Stand</Name>
<Description>Premium hang-on tree stand with comfort features</Description>
<CategoryExternalId>tree-stands</CategoryExternalId>
<ProductPageUrl>https://gomuddy.com/products/apex-hang-on</ProductPageUrl>
<ImageUrl>https://cdn.gomuddy.com/products/apex-main.jpg</ImageUrl>
<Brand>
<Name>Muddy</Name>
<ExternalId>muddy</ExternalId>
</Brand>
<UPCs>
<UPC>012345678901</UPC>
</UPCs>
</Product>
</Products>
</Feed>
Display Reviews
// Display reviews on product page
add_action( 'bigcommerce/template/product/after_content', function() {
global $post;
$bc_id = get_post_meta( $post->ID, 'bigcommerce_id', true );
echo '<div id="BVRRContainer" data-product-id="' . esc_attr( $bc_id ) . '"></div>';
} );
Back in Stock Notifications v1.2.4
Product availability alerts with Klaviyo integration for BigCommerce products.
Features
- AJAX form submission
- Klaviyo list synchronization
- Product feed generation
- WooCommerce/BigCommerce stock monitoring
- Email notifications
Installation
wp plugin install /path/to/back-in-stock-notifications-v1.2.4.zip --activate
Configuration:
// wp-config.php
define( 'KLAVIYO_API_KEY', 'pk_xxxxxxxxxxxxx' );
define( 'KLAVIYO_BACK_IN_STOCK_LIST_ID', 'XTXbL5' );
Usage
Display form on out-of-stock products:
// Check if product is out of stock
$inventory = get_post_meta( $product_id, 'bigcommerce_inventory', true );
if ( $inventory <= 0 ) :
?>
<div class="back-in-stock-form">
<h3>Get Notified When Back in Stock</h3>
<form class="bisn-form" data-product-id="<?php echo esc_attr( $product_id ); ?>">
<input type="email" name="email" placeholder="Your Email" required>
<button type="submit">Notify Me</button>
</form>
</div>
<?php
endif;
JavaScript Handler:
document.querySelectorAll('.bisn-form').forEach(form => {
form.addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const productId = e.target.dataset.productId;
const response = await fetch('/wp-json/bisn/v1/subscribe', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: formData.get('email'),
product_id: productId
})
});
if (response.ok) {
alert('You will be notified when this product is back in stock!');
}
});
});
Klaviyo Integration
// Subscribe customer to Klaviyo list
function bisn_subscribe_to_klaviyo( $email, $product_id ) {
$product_name = get_the_title( $product_id );
$product_url = get_permalink( $product_id );
$klaviyo_api = 'https://a.klaviyo.com/api/v2/list/' . KLAVIYO_BACK_IN_STOCK_LIST_ID . '/subscribe';
$data = [
'api_key' => KLAVIYO_API_KEY,
'profiles' => [
[
'email' => $email,
'properties' => [
'BackInStockProduct' => $product_name,
'BackInStockProductURL' => $product_url,
'BackInStockProductID' => $product_id
]
]
]
];
wp_remote_post( $klaviyo_api, [
'headers' => [ 'Content-Type' => 'application/json' ],
'body' => json_encode( $data )
] );
}
Gift Certificate Creator v1.0.0
Custom gift certificate creation and redemption system integrated with BigCommerce cart.
Features
- Custom certificate amounts
- Personalized messages
- Email delivery
- PDF generation
- Redemption tracking
- BigCommerce cart integration
Installation
wp plugin install /path/to/gift-certificate-creator-v1.0.0.zip --activate
Usage
Gift Certificate Form:
// Shortcode: [muddy_gift_certificate]
add_shortcode( 'muddy_gift_certificate', function() {
ob_start();
?>
<form class="gift-certificate-form" method="post">
<label>Amount
<select name="amount" required>
<option value="25">$25</option>
<option value="50">$50</option>
<option value="100">$100</option>
<option value="custom">Custom Amount</option>
</select>
</label>
<input type="number" name="custom_amount" placeholder="Enter custom amount" min="10" max="1000">
<label>Recipient Name
<input type="text" name="recipient_name" required>
</label>
<label>Recipient Email
<input type="email" name="recipient_email" required>
</label>
<label>Personal Message
<textarea name="message" rows="4"></textarea>
</label>
<label>Delivery Date
<input type="date" name="delivery_date" min="<?php echo date( 'Y-m-d' ); ?>">
</label>
<button type="submit">Purchase Gift Certificate</button>
</form>
<?php
return ob_get_clean();
} );
Processing:
add_action( 'init', function() {
if ( isset( $_POST['recipient_email'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'gift_certificate' ) ) {
$amount = $_POST['amount'] === 'custom' ? floatval( $_POST['custom_amount'] ) : floatval( $_POST['amount'] );
// Generate certificate code
$code = strtoupper( substr( md5( uniqid( rand(), true ) ), 0, 12 ) );
// Save to database
global $wpdb;
$wpdb->insert( $wpdb->prefix . 'gift_certificates', [
'code' => $code,
'amount' => $amount,
'balance' => $amount,
'recipient_name' => sanitize_text_field( $_POST['recipient_name'] ),
'recipient_email' => sanitize_email( $_POST['recipient_email'] ),
'message' => sanitize_textarea_field( $_POST['message'] ),
'delivery_date' => sanitize_text_field( $_POST['delivery_date'] ),
'purchaser_id' => get_current_user_id(),
'created_at' => current_time( 'mysql' )
] );
// Send email
muddy_send_gift_certificate_email( $code );
wp_redirect( add_query_arg( 'certificate', 'success' ) );
exit;
}
} );
Redemption
// Apply gift certificate to cart
add_action( 'wp_ajax_apply_gift_certificate', function() {
check_ajax_referer( 'gift_certificate_nonce' );
$code = sanitize_text_field( $_POST['code'] );
global $wpdb;
$certificate = $wpdb->get_row( $wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}gift_certificates WHERE code = %s AND balance > 0",
$code
) );
if ( $certificate ) {
// Apply to cart
WC()->session->set( 'gift_certificate_code', $code );
WC()->session->set( 'gift_certificate_amount', $certificate->balance );
wp_send_json_success( [
'message' => 'Gift certificate applied!',
'balance' => $certificate->balance
] );
} else {
wp_send_json_error( 'Invalid or expired gift certificate code.' );
}
} );
Narvar Middleware v1.2.7
Order tracking and shipment integration with webhook processing and automated cron jobs.
Features
- Order synchronization
- Shipment tracking updates
- Webhook processing
- Queue system with retry logic
- BigCommerce API integration
- Narvar API integration
Installation
wp plugin install /path/to/narvar-middleware-v1.2.7.zip --activate
Configuration:
// wp-config.php
define( 'NARVAR_API_KEY', 'your_api_key' );
define( 'NARVAR_RETAILER_ID', 'muddy' );
define( 'NARVAR_WEBHOOK_SECRET', 'your_webhook_secret' );
Order Synchronization
// Sync order to Narvar when created
add_action( 'bigcommerce/webhooks/order/created', function( $order_id ) {
$order = get_bigcommerce_order( $order_id );
$narvar_data = [
'order_number' => $order->id,
'order_date' => $order->date_created,
'customer' => [
'email' => $order->billing_address->email,
'first_name' => $order->billing_address->first_name,
'last_name' => $order->billing_address->last_name
],
'shipping_address' => [
'street1' => $order->shipping_address->street_1,
'city' => $order->shipping_address->city,
'state' => $order->shipping_address->state,
'zip' => $order->shipping_address->zip,
'country' => $order->shipping_address->country
],
'items' => array_map( function( $item ) {
return [
'sku' => $item->sku,
'name' => $item->name,
'quantity' => $item->quantity,
'price' => $item->price
];
}, $order->products )
];
// Send to Narvar API
narvar_middleware_send_order( $narvar_data );
} );
Webhook Handler
// Receive shipment updates from Narvar
add_action( 'rest_api_init', function() {
register_rest_route( 'narvar/v1', '/webhook', [
'methods' => 'POST',
'callback' => 'narvar_webhook_handler',
'permission_callback' => 'narvar_verify_webhook_signature'
] );
} );
function narvar_webhook_handler( $request ) {
$payload = $request->get_json_params();
if ( $payload['event_type'] === 'shipment.updated' ) {
$order_id = $payload['order_number'];
$tracking_number = $payload['tracking_number'];
$carrier = $payload['carrier'];
// Update BigCommerce order
update_bigcommerce_order_tracking( $order_id, $tracking_number, $carrier );
// Trigger email notification
do_action( 'muddy_order_shipped', $order_id, $tracking_number );
}
return rest_ensure_response( [ 'status' => 'success' ] );
}
Plugin Dependencies
All Suma plugins require:
- WordPress 6.0+
- PHP 8.1+
- BigCommerce for WordPress plugin (for e-commerce plugins)
Individual plugin dependencies are managed via Composer when applicable.