visualbuilder / filament-hubspot
Syncs leads from HubSpot
Fund package maintenance!
Visual Builder
Requires
- php: ^8.1
- filament/filament: ^3.0
- hubspot/api-client: ^12.0
- spatie/laravel-package-tools: ^1.15.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.72
- nunomaduro/collision: ^7.9
- orchestra/testbench: ^8.0
- pestphp/pest: ^2.1
- pestphp/pest-plugin-arch: ^2.0
- pestphp/pest-plugin-laravel: ^2.0
README
📌 Overview
This package provides:
- A Laravel Facade wrapper for the HubSpot API PHP Library.
- A customizable webhook (
/api/hubspot/webhook
) to receive contact updates from HubSpot. - An event-driven sync system (
SyncHubspotContactListener
) to automatically sync contacts from HubSpot to Laravel.
This package is a quick-start solution for integrating HubSpot contacts into a Laravel + Filament sales pipeline.
🚀 Installation
Install the package via Composer:
composer require visualbuilder/filament-hubspot
Publish the config file:-
php artisan vendor:publish --tag="filament-hubspot-config"
If you wish to use the provided lead model then run the install command to setup the migration
php artisan filament-hubspot:install
🔑 HubSpot API Setup
1️⃣ Obtain HubSpot API Credentials
- Go to HubSpot > Settings > Account Management > Integrations.
- Navigate to Connected Apps or Private Apps.
- Generate an Access Token and Client Secret.
2️⃣ Add credentials to .env
HUBSPOT_ACCESS_TOKEN=pat-eu1-xxxxx HUBSPOT_CLIENT_SECRET=xxxxx-xxx-xxxxx
Testing the connection. The HubSpot API should now be available on the HubSpot Facade. You can test with tinker or in a console command:-
$response = HubSpot::crm()->contacts()->basicApi()->getPage(); foreach ($response->getResults() as $contact) { dump($contact->getProperties()); }
Webhook
On your app, add the events that should trigger a webhook and point to yourdomain.com/api/hubspot/webhook
Local Webhook testing
For local testing of webhooks use ngrok or smee to route requests to your local server
ngrok http localhost:80
Which should provide a url which can be used in HubSpot:-
Forwarding https://a5ed-18-170-5-16.ngrok-free.app -> http://localhost:80
Paste this URL into the Hubspot App webhooks section and define your events to trigger call. On this page you can send a test webhook.
Ngrok should output something like
05:20:45.763 GMT POST /api/hubspot/webhook 200 OK
This indicates the POST has been received and validated and the HubspotWebhookReceived
Event will be triggered
The provided SyncHubspotContactListener
will be called each time the Webhook is received.
Add your own custom Listeners in the config
/** * What to do when a webhook is received */ 'listeners' => [ Visualbuilder\FilamentHubspot\Events\HubspotWebhookReceived::class => [ Visualbuilder\FilamentHubspot\Listeners\SyncHubspotContactListener::class, // Additional listeners can be added here... ], ],
If you are getting 401 Unauthorized, check the keys and your server time. Valid requests must be within 5 minutes so clocks must be correct.
Synching a local model
Set your model that should receive the HubSpot Contact and set which attributes to update.
/* |-------------------------------------------------------------------------- | HubSpot Webhook Options |-------------------------------------------------------------------------- | Enabling adds a route at /api/hubspot/webhook | Valid requests will trigger an event HubspotWebhookReceived | */ 'webhook' => [ 'enabled' => env('HUBSPOT_WEBHOOK_ENABLED', true), 'slug' => env('HUBSPOT_WEBHOOK_SLUG', 'api/hubspot/webhook'), /** * Replace this with your own Contact Model preference */ 'local_contact_model' => \App\Models\Lead::class, 'match_on_attribute' => [ 'hubspot' => 'email', 'localModel' => 'email' ],
Set field mapping
/* |-------------------------------------------------------------------------- | HubSpot Contact to local Model mappings |-------------------------------------------------------------------------- | Setup hubspot fields => model attribute mapping | These fields will be requested from hubspot, the values are the model mappings | */ 'mappings' => [ 'firstname' => ['attribute' => 'first_name'], 'lastname' => ['attribute' => 'last_name'], 'email' => ['attribute' => 'email'], 'company' => ['attribute' => 'company'], 'website' => ['attribute' => 'website'], 'jobtitle' => ['attribute' => 'job_title'], 'message' => ['attribute' => 'message'], 'lastmodifieddate' => ['attribute' => 'updated_at'], 'lifecyclestage' => ['attribute' => null], 'hs_object_id' => ['attribute' => 'hs_id'], // Relations can be added and auto created if not existing // in this case leadsource may contain LinkedIn, Facebook etc as a string and will populate a related model if the source is not found 'leadsource' => [ 'relation' => 'leadSource', 'lookup_field' => 'name', // the column to find or create related model 'foreign_key' => 'lead_source_id', // optional, otherwise inferred automatically 'not_found_action' => 'create', // use ignore or create missing lookup relation ], ],
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
Credits
License
The MIT License (MIT). Please see License File for more information.