HubSpot Sync - Milli
Consolidated HubSpot integration for WooCommerce. Syncs orders, contacts, deals, and custom checkout fields to HubSpot CRM.
by Team Outsiders · github.com/thedevcave/hubspot-sync-milli · website
Install
The author publishes release zips, so WP-CLI can install straight from GitHub:
wp plugin install https://github.com/thedevcave/hubspot-sync-milli/releases/download/1.0.5/hubspot-sync-milli.zipReadme
HubSpot Sync - Milli
A comprehensive WordPress plugin that provides complete WooCommerce-to-HubSpot integration with advanced abandoned cart tracking, device management, and external system integration. Built by Team Outsiders as a modern, consolidated replacement for multiple HubSpot gateway plugins.
✨ Key Features
🛒 Advanced Abandoned Cart Tracking
- Real-Time Monitoring: Tracks 21+ checkout fields with debounced AJAX calls
- Smart Cart Conversion: Converts abandoned cart deals to completed orders (prevents duplicates)
- Persistent Hash System: Maintains cart identity across sessions and page reloads
- Customer Journey Tracking: Complete lifecycle from abandonment to conversion in single HubSpot deal
🔄 Comprehensive Sync System
- Contact Management: Bi-directional sync with custom field mapping
- Deal Lifecycle: Automated deal creation, updates, and stage transitions
- Device Integration: Serial number tracking from fulfillment to HubSpot custom objects
- Background Processing: Non-blocking async sync with cron job scheduling
- External API Ready: REST endpoints for ShipHero and other fulfillment systems
📱 Device & Serial Number Management
- Order Item Tracking: Serial numbers stored in WooCommerce order meta
- HubSpot Device Objects: Automatic device creation with full property mapping
- Association Management: Links devices to contacts, deals, and companies
- ShipHero Integration: Automatic monitoring of existing ShipHero webhooks for serial numbers
- Batch Processing: Handle multiple serial number assignments efficiently
- Manual Sync Options: Admin controls for immediate device synchronization
⚙️ Enterprise-Grade Configuration
- Environment Detection: Staging, Production, Development modes with safe testing
- Custom Field Mapping: Flexible mapping between WooCommerce and HubSpot properties
- Deal Stage Management: Configurable stages for all order statuses including abandonment
- Sync Triggers: Granular control over when syncing occurs
- Rate Limiting: Built-in API throttling to prevent HubSpot rate limits
🛡️ Security & Reliability
- Nonce Verification: Secure AJAX endpoints with proper authentication
- Data Sanitization: All inputs sanitized and validated
- Error Handling: Comprehensive try-catch blocks with detailed logging
- Fault Tolerance: Graceful degradation when external services are unavailable
- Debug Mode: Detailed logging for troubleshooting and monitoring
🚀 Installation
- Upload the
hubspot-sync-millifolder to/wp-content/plugins/ - Activate the plugin through the WordPress 'Plugins' menu
- Configure settings at Settings → HubSpot Sync
Requirements:
- WordPress 5.0+
- WooCommerce 4.0+
- PHP 7.4+
- HubSpot Private App with CRM permissions
⚡ Quick Configuration
1. HubSpot API Setup
Create a HubSpot Private App with these scopes:
• crm.objects.contacts.read
• crm.objects.contacts.write
• crm.objects.deals.read
• crm.objects.deals.write
• crm.objects.companies.read
• crm.objects.companies.write
• crm.objects.custom.read
• crm.objects.custom.write
2. Essential Settings
- API Token: Your HubSpot Private App access token
- Site Prefix: Unique identifier for this site (e.g., "MyStore")
- Deal Pipeline: HubSpot pipeline ID for WooCommerce deals
- Owner ID: Default HubSpot owner for new contacts/deals
3. Deal Stage Mapping
| Order Status | HubSpot Stage | Purpose |
|---|---|---|
| Abandoned Cart | abandoned_cart |
Real-time cart tracking |
| Pending Payment | pending_payment |
Payment gateways like AfterPay |
| On Hold | on_hold |
Orders awaiting payment processing |
| Processing | processing |
Orders being fulfilled |
| Completed | won |
Successfully completed orders |
| Cancelled | cancelled |
Customer cancellations |
| Refunded | refunded |
Processed refunds |
| Failed | failed |
Payment failures |
🎯 Core Functionality
Abandoned Cart System
Real-time tracking prevents deal duplication:
graph LR
A[Checkout Form] -->|Field Changes| B[Debounced AJAX]
B --> C[Cart Hash Generated]
C --> D[HubSpot Deal Created]
D -->|Customer Returns| E[Same Deal Updated]
E -->|Order Complete| F[Deal Converted]
F --> G[Single Deal Journey]
Benefits:
- ✅ Single deal tracks complete customer journey
- ✅ No duplicate deals for same customer
- ✅ Accurate conversion rate reporting
- ✅ Preserved attribution and source data
Device Management Workflow
Complete serial number to HubSpot integration:
- Order Completion: Customer places order
- Fulfillment: ShipHero (or external system) ships product
- Serial Assignment: Webhook or API call adds serial number to order
- Automatic Detection: Plugin monitors order meta updates (non-destructive)
- Device Creation: HubSpot device object created automatically
- Association: Device linked to contact, deal, and company
📊 Field Mapping
🛒 Checkout Fields Configuration
The plugin supports two checkout field implementations:
Full Checkout Fields (Default)
- Multi-step conditional form with acquisition source dropdown
- Healthcare provider conversation questions
- Conditional provider referral questions
- Provider detail collection (name, clinic, state)
Simplified Checkout Fields
- Single radio button: "Were you referred by a healthcare provider?"
- Yes/No options only
- Streamlined user experience
To Switch to Simplified Checkout:
- Open
hubspot-sync-milli.php - Change:
define( 'HUBSPOT_SYNC_MILLI_USE_SIMPLE_CHECKOUT', true ); - Save the file
Note: Both implementations map to the same HubSpot properties, ensuring data consistency.
Checkout Fields → HubSpot Properties
| Checkout Field | HubSpot Property | Type | Description | Available In |
|---|---|---|---|---|
| Acquisition Source | how_did_you_hear_about_us_consumer |
Dropdown | Marketing attribution | Full Only |
| Clinician Name | referring_clinician |
Text | Healthcare provider | Full Only |
| Clinic State | referring_state |
Dropdown | Provider location | Full Only |
| Clinic Name | referring_clinic |
Text | Practice name | Full Only |
| Provider Conversation | have_you_talked_to_healthcare_provider |
Yes/No | Consultation status | Full Only |
| Provider Referral | did_your_provider_refer_you_to_milli_ |
Yes/No | Referral verification | Both Versions |
Device Properties
| Property | Source | Description |
|---|---|---|
| serial_number | Order meta | Unique device identifier |
| order_id | WooCommerce | Associated order number |
| customer_email | Order billing | Device owner |
| assignment_date | Current time | When device was assigned |
| product_name | Order items | Product associated with device |
🔌 API Integration
REST Endpoints
Add Serial Number
POST /wp-json/hubspot-sync-milli/v1/serial-number
Authorization: Bearer {token}
Content-Type: application/json
{
"order_id": 12345,
"serial_number": "SN123456789"
}
Test Connection
POST /wp-admin/admin-ajax.php
Content-Type: application/x-www-form-urlencoded
action=hubspot_sync_milli_test_connection
&nonce={admin_nonce}
Webhook Integration
ShipHero Integration (Automatic)
The plugin automatically monitors existing ShipHero webhook processing:
// No code changes needed - plugin hooks into existing ShipHero workflow:
// 1. ShipHero webhook → api-shiphero.php (existing)
// 2. Serial numbers saved to order meta (existing)
// 3. Plugin detects meta update → triggers HubSpot device creation (new)
// Monitoring is added via WordPress hooks:
add_action('updated_post_meta', 'on_order_meta_updated', 10, 4);
External Webhook Integration (Manual)
// External systems can trigger serial number assignment
add_action('wp_ajax_nopriv_external_webhook', function() {
$data = json_decode(file_get_contents('php://input'), true);
foreach ($data as $shipment) {
HubSpot_Sync_Milli_Serial_Number_Manager::add_serial_number(
$shipment['Order ID'],
$shipment['Product Serial Number Shipped']
);
}
wp_die('OK');
});
📁 File Structure
hubspot-sync-milli/
├── hubspot-sync-milli.php # Main plugin file
├── README.md # This overview documentation
├── docs/ # Complete documentation library
│ ├── index.md # Documentation homepage
│ ├── ABANDONED_CART.md # Abandoned cart guide
│ ├── SERIAL_NUMBERS.md # Device integration guide
│ ├── CHECKOUT_FIELDS.md # Checkout fields configuration
│ ├── HOOKS_AND_TRIGGERS.md # Developer reference
│ ├── HUBSPOT-SETUP.md # HubSpot configuration guide
│ └── UPDATES.md # Update system documentation
├── includes/
│ ├── class-hubspot-sync-milli.php # Core plugin orchestration
│ ├── class-admin-settings.php # Admin interface & settings
│ ├── class-hubspot-api.php # HubSpot API wrapper
│ ├── class-checkout-fields.php # Full checkout fields implementation
│ ├── class-checkout-fields-simple.php # Simplified checkout fields
│ ├── class-sync-manager.php # Sync orchestration & logic
│ ├── class-abandoned-cart-tracker.php # Real-time cart tracking
│ └── class-serial-number-manager.php # Device management utilities
├── assets/
│ ├── css/
│ │ ├── admin.css # Admin interface styling
│ │ └── checkout.css # Checkout field styling
│ └── js/
│ ├── admin.js # Admin functionality
│ ├── checkout.js # Checkout interactions
│ └── abandoned-cart-tracker.js # Real-time form monitoring
├── examples/
│ └── serial-number-examples.php # Integration code examples
└── tests/
├── complete-system-breakdown.php # Detailed functionality trace
└── executable-test.php # Runnable test simulation
🧪 Testing & Debugging
Comprehensive Testing Framework
The plugin includes detailed testing tools:
Executable Test Suite
# Run complete system test via WP-CLI
wp eval-file wp-content/plugins/hubspot-sync-milli/tests/executable-test.php
# Output shows complete buying process simulation:
# ✓ Stage 1: Checkout page load
# ✓ Stage 2: Form interaction (abandonment)
# ✓ Stage 3: HubSpot sync
# ✓ Stage 4: Customer return
# ✓ Stage 5: Order completion
# ✓ Stage 6: Cart conversion
# ✓ Stage 7: Background sync
# ✓ Stage 8: Device assignment
Debug Logging
Enable in Settings → HubSpot Sync → Advanced:
[HubSpot Sync] Generated cart hash: abc123... for email: customer@example.com
[HubSpot Sync] Abandoned cart synced. Deal ID: 12345678
[HubSpot Sync] Converting cart abc123... to order 12345
[HubSpot Sync] Device SN123456 created with ID: 87654321
Manual Testing Checklist
- [ ] Abandoned Cart: Fill checkout form, verify HubSpot deal creation
- [ ] Cart Return: Modify form, confirm same deal updated
- [ ] Order Completion: Complete purchase, verify deal conversion
- [ ] Device Assignment: Add serial number, confirm HubSpot device creation
- [ ] ShipHero Integration: Test with existing api-shiphero.php webhook
- [ ] Admin Interface: Test connection, manual sync, bulk actions
⚙️ Advanced Usage
Background Sync System
// Orders sync in background (60-second delay)
wp_schedule_single_event(time() + 60, 'hubspot_sync_milli_cron', [$order_id]);
// Rate limiting prevents API throttling
usleep(110000); // 110ms between API calls
Custom Field Integration
// Add custom fields to checkout
add_action('woocommerce_after_order_notes', function($checkout) {
woocommerce_form_field('custom_field', [
'type' => 'text',
'label' => 'Custom Information',
'id' => 'custom_field'
]);
});
// Map to HubSpot property
add_filter('hubspot_sync_milli_contact_data', function($data, $order) {
$data['custom_property'] = $order->get_meta('custom_field');
return $data;
}, 10, 2);
Serial Number Batch Processing
// Process CSV export from fulfillment system
$csv_data = [
['Order ID' => '12345', 'Product Serial Number Shipped' => 'SN123456'],
['Order ID' => '12346', 'Product Serial Number Shipped' => 'SN789012']
];
$result = HubSpot_Sync_Milli_Serial_Number_Manager::batch_add_serial_numbers($csv_data);
// Result: ['success' => true, 'processed' => 2, 'errors' => []]
🛠️ Hooks & Filters
Custom Actions
// Before/after sync events
do_action('hubspot_sync_milli_before_contact_sync', $contact_data, $order);
do_action('hubspot_sync_milli_after_contact_sync', $hubspot_contact_id, $order);
do_action('hubspot_sync_milli_before_deal_sync', $deal_data, $order);
do_action('hubspot_sync_milli_after_deal_sync', $hubspot_deal_id, $order);
// Device processing
do_action('hubspot_sync_milli_process_serial_number', $order_id, $serial_number);
Data Filters
// Modify data before HubSpot sync
add_filter('hubspot_sync_milli_contact_data', 'modify_contact_data', 10, 2);
add_filter('hubspot_sync_milli_deal_data', 'modify_deal_data', 10, 2);
add_filter('hubspot_sync_milli_device_data', 'modify_device_data', 10, 2);
🔧 Troubleshooting
Read the full README on GitHub →