Search by

datomatic / laravel-hubspot-email-notification-channel

trippo

Laravel Channel to save email and notifications on Hubspot Email

Package info

github.com/datomatic/laravel-hubspot-email-notification-channel

pkg:composer/datomatic/laravel-hubspot-email-notification-channel

Fund package maintenance!

Datomatic

Statistics

Installs: 13 343

Dependents: 0

Suggesters: 0

Stars: 5

Open Issues: 0

v2.0.0 2026-09-22 15:33 UTC

This package is auto-updated.

Last update: 2026-09-22 15:47:38 UTC


README

Latest Version on Packagist Software License Quality Score Total Downloads

This package makes it easy to log notifications to Hubspot Email Engagement V3 with Laravel >= 12.x

Contents

Installation

You can install the package via composer:

composer require datomatic/laravel-hubspot-email-notification-channel

Setting up the HubspotEmail service

Create a Private App in Hubspot and copy its access token. Hubspot API keys were sunset on November 30th 2022 and are no longer accepted.

Configure your Hubspot API on .env

HUBSPOT_ACCESS_TOKEN=XXXXXXXX
HUBSPOT_OWNER_ID=XXX # an Hubspot owner id to save as email creator

To publish the config file to config/hubspot.php run:

php artisan vendor:publish --provider="Datomatic\LaravelHubspotEmailNotificationChannel\HubspotEmailServiceProvider"

This will publish a file hubspot.php in your config directory with the following contents:

// config/hubspot.php

return [
    'access_token' => env('HUBSPOT_ACCESS_TOKEN'),
    'hubspot_owner_id' => env('HUBSPOT_OWNER_ID'),
    'company_email_associations' => true,
    'retry' => [
        'times' => env('HUBSPOT_RETRY_TIMES', 3),
        'sleep_milliseconds' => env('HUBSPOT_RETRY_SLEEP_MILLISECONDS', 11 * 1000),
    ],
];

Hubspot enforces its rate limit over a ten second window, so the default retry waits eleven seconds between attempts. Three attempts means a failing call can block for over twenty seconds, which matters inside a queued job: lower HUBSPOT_RETRY_TIMES to 1 to disable retrying altogether.

Usage

You can now use the channel in your via() method inside the Notification class.

Email notification

Your Notification class must have toMail method. The package accepts: MailMessage lines notifications, MailMessage view notifications and Markdown mail notifications.

Data stored on Hubspot:

  • Hubspot Contact Id => The Notifiable Model must implement Datomatic\LaravelHubspotEmailNotificationChannel\Contracts\HasHubspotContact
  • Send at timestamp
  • subject
  • mail text (the html of the email or the toHubspotTextMail method of notification)

Example

Notification example

use Datomatic\LaravelHubspotEmailNotificationChannel\HubspotEmailChannel;
use Illuminate\Notifications\Notification;

class OrderConfirmation extends Notification
{
    ...
    public function via($notifiable)
    {
        return ['mail', HubspotEmailChannel::class]];
    }

    public function toMail($notifiable)
    {
        $message = (new MailMessage)
            ->subject(__('order.order_confirm', ['code' => $this->order->code]));

        return $message->view(
            'emails.order', [
                'title' => __('order.order_confirm', ['code' => $this->order->code]),
                'order' => $this->order
            ]
        );
    }

    //Optional text method
    public function toHubspotTextMail($notifiable):string
    {
        return 'text of message to put on hubspot';
    }
    ...
}

Send text version of html email

An example of use of toHubspotTextMail method is to send the text version of the email.

use Soundasleep\Html2Text;
class OrderConfirmation extends Notification
{
    ...

    public function toHubspotTextMail(mixed $notifiable): string
    {
        return Html2Text::convert($this->toMail($notifiable)->render());
    }
}

Model example

namespace App\Models;

use Datomatic\LaravelHubspotEmailNotificationChannel\Contracts\HasHubspotContact;
use Illuminate\Notifications\Notification;

class User extends Authenticatable implements HasHubspotContact
{
    ...
    public function getHubspotContactId(Notification $notification): int|string|null
    {
        return $this->hubspot_contact_id;
    }
    ...
}

Returning null skips logging the notification to Hubspot.

Handling a stale contact id

Since the 2026-09 write validation, Hubspot rejects an association to a contact id it cannot resolve instead of silently accepting it. That surfaces as a HubspotObjectNotFound, which carries the decoded error body:

use Datomatic\LaravelHubspotEmailNotificationChannel\Exceptions\HubspotObjectNotFound;

try {
    $user->notify(new OrderConfirmation($order));
} catch (HubspotObjectNotFound $e) {
    // ["CONTACT=838442890479 is not valid"]
    logger()->warning('Stale Hubspot contact', $e->invalidObjectIds());

    $user->update(['hubspot_contact_id' => null]);
}

HubspotObjectNotFound extends CouldNotSendNotification and also exposes payload(), category() and correlationId(). Note that the email object is created before the association is attempted, so a rejected association leaves an orphaned email in Hubspot.

Dynamic Contact Owner

use Datomatic\LaravelHubspotEmailNotificationChannel\HubspotEmailChannel;
use Illuminate\Notifications\Notification;

class PersonalMessage extends Notification
{
    ...

    public function via($notifiable)
    {
        return ['mail', HubspotEmailChannel::class]];
    }

    public function toMail($notifiable)
    {
        $message = (new MailMessage)
            ->subject(__('messages.personal_subject'))
            ->from($this->employee->email, $this->employee->name)
            ->metadata('hubspot_owner_id', $this->employee->hubspot_owner_id);

        return $message->view(
            'messages.personal', [
                'title' => __('messages.personal_welcome', ['recipient' => $notifiable->name]),
                'employee' => $this->employee
            ]
        );
    }

    ...
}

Changelog

Please see CHANGELOG for more information what has changed recently.

Testing

$ composer test

Security

If you discover any security related issues, please email info@albertoperipolli.com instead of using the issue tracker.

Contributing

Please see CONTRIBUTING for details.

Credits

License

The MIT License (MIT). Please see License File for more information.