Skip to content

HubSpot Integration Does Not Support Custom Objects #2649

@schindlerchristian

Description

@schindlerchristian

Describe the bug

Summary:
The HubSpot CRM integration does not support HubSpot Custom Objects. Form submissions fail when fields are mapped to custom properties that belong to Custom Objects with portal-specific Object Type IDs (e.g., 2-21479350).

Current Behavior:
Formie hardcodes Object Type IDs to only support standard objects:

  • Contact: 0-1
  • Company: 0-2
  • Custom Objects: ❌ Not supported

When submitting a form with custom properties, HubSpot returns:

400 Bad Request: Property values were not valid
{
  "message": "Required field '2-21479350/submitter_firstname' is missing"
}

Expected Behavior:
Formie should support HubSpot Custom Objects by allowing users to configure or automatically detecting the correct Object Type ID for each field, enabling successful form submissions to Custom Objects.

Technical Details:
In vendor/verbb/formie/src/integrations/crm/HubSpot.php (lines ~582-593), the objectTypeId is hardcoded:

$objectTypeId = str_replace(['CONTACT', 'COMPANY'], ['0-1', '0-2'], ($handleParts[0] ?? 'CONTACT'));

This prevents any Custom Object from being used, as they have portal-specific IDs like 2-21479350.

What HubSpot API expects:

{
  "fields": [
    {
      "objectTypeId": "2-21479350",
      "name": "submitter_firstname",
      "value": "John"
    }
  ]
}

What Formie currently sends:

{
  "fields": [
    {
      "objectTypeId": "0-1",
      "name": "submitter_firstname",
      "value": "John"
    }
  ]
}

Steps to reproduce

  1. In HubSpot, create a Custom Object (e.g., "Event Registrations") with custom properties (e.g., submitter_firstname, event_date)
  2. In Craft CMS, create a Formie form with fields matching these properties
  3. Configure the HubSpot integration in Formie
  4. Map form fields to the custom properties from step 1
  5. Submit the form via frontend

Result: Form submission fails with 400 Bad Request - "Required field 'X-XXXXXXXX/property_name' is missing"

Expected: Form submission succeeds and data appears in HubSpot Custom Object

Form settings

  • Multi-page form: No (but also affects multi-page forms)
  • Submission Method: Ajax
  • Client-side Validation: Yes
  • Custom Form Templates: No

Craft CMS version

5.8.20

Plugin version

3.1.6 (also affects previous versions)

Multi-site?

No

Additional context

Current Workaround

We've had to implement a direct vendor patch to transform specific fields:

// In vendor/verbb/formie/src/integrations/crm/HubSpot.php
$prefixFields = ['submitter_', 'event', 'appointment', 'with_visitor'];

$needsTransform = false;
foreach ($prefixFields as $prefix) {
    if (str_starts_with($fieldName, $prefix) || $fieldName === rtrim($prefix, '_')) {
        $needsTransform = true;
        break;
    }
}

if ($needsTransform) {
    $objectTypeId = '2-21479350'; // Custom Object Type ID
}

Limitations:

  • Must be reapplied after every Formie update
  • Hardcoded Object Type ID
  • Not portable across different HubSpot portals

Proposed Solutions

Option 1: Field-Level Configuration
Add an optional objectTypeId field to the field mapping settings in the Control Panel:

// Field mapping configuration
[
    'handle' => 'submitterFirstname',
    'hubspot_property' => 'submitter_firstname',
    'objectTypeId' => '2-21479350',  // User-configurable
]

Option 2: Automatic API Detection (Preferred)
Query HubSpot's API to automatically determine the correct Object Type ID:

// GET https://api.hubapi.com/crm/v3/properties/contacts/{propertyName}
// Response includes the correct objectTypeId

This would work automatically without user configuration and adapt to any HubSpot portal setup.

Option 3: Hybrid Approach
Combine both: Auto-detect via API as default, with manual override option for edge cases.

Impact

This issue affects any Formie user who:

  • Uses HubSpot Custom Objects
  • Has portal-specific custom properties
  • Needs to submit forms to non-standard HubSpot objects

Use Cases

  1. Event Registrations: Custom object for tracking event attendees with specific fields
  2. Product Demos: Custom object for demo requests
  3. Partner Applications: Custom object for partner onboarding workflows
  4. Lead Scoring: Custom objects with specialized lead qualification fields

Relevant HubSpot Documentation

Implementation Suggestion

Adding automatic Object Type detection would require:

  1. API Integration:
protected function getObjectTypeIdForProperty(string $propertyName): string
{
    $cached = Craft::$app->cache->get("hubspot_objecttype_{$propertyName}");
    if ($cached) {
        return $cached;
    }
    
    try {
        $response = $this->request('GET', "crm/v3/properties/contacts/{$propertyName}");
        $objectTypeId = $response['objectTypeId'] ?? '0-1';
        
        Craft::$app->cache->set("hubspot_objecttype_{$propertyName}", $objectTypeId, 86400);
        return $objectTypeId;
    } catch (\Exception $e) {
        return '0-1'; // Fallback to Contact
    }
}
  1. Backward Compatibility:
// Use detected ID, fall back to current behavior
$objectTypeId = $this->getObjectTypeIdForProperty($fieldName) 
    ?? str_replace(['CONTACT', 'COMPANY'], ['0-1', '0-2'], ($handleParts[0] ?? 'CONTACT'));

Additional Notes

  • This affects HubSpot Enterprise customers who have Custom Objects enabled
  • The workaround requires direct vendor modification, which is not maintainable
  • We have detailed logging showing the exact payload differences

Environment

  • PHP Version: 8.2.26
  • Database: MySQL 8.0
  • HubSpot Portal: Enterprise (Custom Objects enabled)
  • Other Plugins: Standard Craft CMS setup, no conflicting integrations

This issue prevents Formie from being compatible with HubSpot's full CRM capabilities. We believe supporting Custom Objects would be a valuable enhancement for the Formie community. 🙏

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions