https://github.com/whilesmartphp/eloquent-outreach
Host-agnostic user outreach for Laravel: compose messages with a call to action, target audiences, and track per-recipient deliveries across pluggable channels.
https://github.com/whilesmartphp/eloquent-outreach
Last synced: 24 days ago
JSON representation
Host-agnostic user outreach for Laravel: compose messages with a call to action, target audiences, and track per-recipient deliveries across pluggable channels.
- Host: GitHub
- URL: https://github.com/whilesmartphp/eloquent-outreach
- Owner: whilesmartphp
- License: mit
- Created: 2026-06-28T09:55:25.000Z (30 days ago)
- Default Branch: dev
- Last Pushed: 2026-06-28T09:55:40.000Z (30 days ago)
- Last Synced: 2026-06-29T00:05:28.392Z (29 days ago)
- Language: PHP
- Size: 14.6 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# Whilesmart Eloquent Outreach
Host-agnostic user outreach for Laravel. Compose a message with a call to action, target an audience, and track a per-recipient delivery, all over channels your app implements. The package owns the workflow; your app owns how recipients are found, addressed, personalized, and sent.
## Installation
```bash
composer require whilesmart/eloquent-outreach
php artisan vendor:publish --tag=outreach-migrations
php artisan migrate
```
## Concepts
- **Outreach** — one composed message: subject, body, CTA (`cta_label` + `cta_url`), `channel`, `audience` criteria, status, optional `scheduled_at`, and rolled-up `stats`. Optional polymorphic `owner` (sender) and `campaign` (a campaign "has many" outreaches).
- **Delivery** — one row per recipient, with status and timestamps. This is what later per-recipient actions (resend, view, mark) hang off.
## What the host implements
```php
use Whilesmart\Outreach\Contracts\AudienceResolver; // criteria -> recipient models
use Whilesmart\Outreach\Contracts\MessageRenderer; // outreach + recipient -> RenderedMessage
use Whilesmart\Outreach\Contracts\OutreachChannel; // deliver a RenderedMessage
```
Bind your implementations in a service provider:
```php
$this->app->bind(AudienceResolver::class, MyAudienceResolver::class);
$this->app->bind(OutreachChannel::class, MyEmailChannel::class);
// MessageRenderer defaults to attribute token replacement ({{first_name}});
// bind your own for richer templating.
```
Safe defaults ship out of the box: the audience resolves to nobody and the channel sends nowhere until you bind real ones.
## Sending
```php
use Whilesmart\Outreach\Models\Outreach;
use Whilesmart\Outreach\Services\OutreachDispatcher;
$outreach = Outreach::create([
'channel' => 'email',
'subject' => 'Hi {{first_name}}',
'body' => 'We added something you will like.',
'cta_label' => 'Open Trakli',
'cta_url' => 'https://trakli.app/dashboard',
'audience' => ['type' => 'inactive', 'days' => 30],
]);
app(OutreachDispatcher::class)->dispatch($outreach);
```
The dispatcher resolves the audience, creates a `Delivery` per recipient, renders and sends each through the bound channel, rolls the results onto the outreach, and emits `OutreachDispatched`, `DeliverySucceeded`, and `DeliveryFailed` for the host to bridge.
## Campaigns
An outreach can belong to a campaign via the optional `campaign` morph, so a campaign (in your app or another package) can own many outreaches without this package depending on it.
## License
MIT. WhileSmart LTD.