Creating Hooks
This guide explains how to create, register, and manage hooks in Mumara Campaigns.
Setting Up Your Hook File
File Location
Create your hook files in the /includes/hooks/ directory:
cd /path/to/mumara
touch includes/hooks/my-custom-hooks.php
Basic Structure
Every hook file should follow this structure:
<?php
/**
* My Custom Hooks
*
* Description of what these hooks do
*/
// Register your hooks here
add_hook('HookName', priority, function($vars) {
// Your code
});
Registering Hooks
The add_hook Function
Use add_hook() to register a callback function for a specific hook:
add_hook(string $hook, int $priority, callable $function)
Parameters:
| Parameter | Type | Description |
|---|---|---|
$hook | string | The name of the hook to attach to |
$priority | int | Execution order (lower numbers run first) |
$function | callable | The callback function to execute |
Priority System
When multiple callbacks are registered to the same hook, they execute in priority order:
// Executes third (priority 10)
add_hook('AddContact', 10, function($vars) {
echo "Third";
});
// Executes first (priority 1)
add_hook('AddContact', 1, function($vars) {
echo "First";
});
// Executes second (priority 5)
add_hook('AddContact', 5, function($vars) {
echo "Second";
});
Priority Guidelines:
- 1-3: Critical operations that must run first
- 5-10: Standard operations
- 10+: Cleanup or logging operations
Using Named Functions
For better debugging and reusability, use named functions with a unique prefix:
// Define the function
function mycompany_log_contact_addition($vars) {
$contactId = $vars['subscriber_id'] ?? null;
if ($contactId) {
Log::info("Contact added: {$contactId}");
}
}
// Register it
add_hook('AddContact', 1, 'mycompany_log_contact_addition');
Accessing Hook Data
Most hooks pass a $vars array containing relevant data about the event.
Inspecting Available Data
To see what data is available in a hook:
add_hook('AddContact', 1, function($vars) {
// Log all available variables
$data = print_r($vars, true);
file_put_contents(storage_path('logs/hook-debug.log'), $data, FILE_APPEND);
});
Common Variables
Depending on the hook, $vars may contain:
$vars = [
'subscriber_id' => 12345, // Contact/subscriber ID
'list_id' => 67, // Contact list ID
'email' => 'user@example.com', // Email address
'campaign_id' => 89, // Campaign ID
'user_id' => 1, // User who triggered the action
// ... additional context-specific data
];
Execution Methods
Synchronous Execution
Use listen_hook() for immediate execution:
// Fire the hook and wait for completion
listen_hook('CustomEvent', ['key' => 'value']);
Asynchronous Execution
Use run_hook_in_background() for queued execution:
// Queue the hook for background processing
run_hook_in_background('CustomEvent', ['key' => 'value']);
Background hooks are processed by Laravel's queue system, making them ideal for:
- Sending notifications
- Syncing with external APIs
- Heavy data processing
- Operations that shouldn't block user requests
Output Hooks
Output hooks return content that gets rendered on the page:
add_hook('HeadTop', 1, function($vars) {
return '<link rel="stylesheet" href="/custom/styles.css">';
});
add_hook('Footer', 1, function($vars) {
return '<script src="/custom/analytics.js"></script>';
});
To retrieve output from hooks:
// Get concatenated output from all callbacks
$html = hook_get_output('Footer', $vars);
// Get output from first callback only
$result = hook_get('Footer', $vars);
// Get array of all callback outputs
$results = hook_get_all('Footer', $vars);
Checking Hook Existence
Before firing a hook, you can check if any callbacks are registered:
if (hook_exist('CustomEvent')) {
listen_hook('CustomEvent', $data);
}
Error Handling
Wrapping in Try-Catch
Always handle exceptions in your hooks:
add_hook('AddContact', 1, function($vars) {
try {
// Your code that might fail
$response = Http::post('https://api.example.com/contacts', [
'email' => $vars['email']
]);
if (!$response->successful()) {
throw new Exception('API request failed');
}
} catch (Exception $e) {
Log::error('Hook error: ' . $e->getMessage());
// Don't re-throw - allow other hooks to continue
}
});
Enabling Error Logging
Enable hook error logging in Application Settings to capture errors:
// When enabled, errors are logged automatically
// Check storage/logs/laravel.log for hook errors
Practical Examples
Example 1: Sync Contacts to External CRM
<?php
// File: includes/hooks/crm-sync.php
add_hook('AddContact', 5, function($vars) {
try {
$contact = \App\Models\Subscriber::find($vars['subscriber_id']);
if (!$contact) {
return;
}
Http::withHeaders([
'Authorization' => 'Bearer ' . config('services.crm.token')
])->post('https://api.mycrm.com/contacts', [
'email' => $contact->email,
'first_name' => $contact->first_name,
'last_name' => $contact->last_name,
'source' => 'mumara'
]);
} catch (Exception $e) {
Log::error('CRM sync failed: ' . $e->getMessage());
}
});
add_hook('DeleteContact', 5, function($vars) {
try {
Http::withHeaders([
'Authorization' => 'Bearer ' . config('services.crm.token')
])->delete('https://api.mycrm.com/contacts/' . $vars['subscriber_id']);
} catch (Exception $e) {
Log::error('CRM delete failed: ' . $e->getMessage());
}
});
Example 2: Custom Analytics Tracking
<?php
// File: includes/hooks/analytics.php
add_hook('BodyEnd', 1, function($vars) {
$trackingId = config('services.analytics.id');
if (!$trackingId) {
return '';
}
return <<<HTML
<script>
(function() {
window.analyticsId = '{$trackingId}';
// Custom analytics code
})();
</script>
HTML;
});
Example 3: Campaign Event Notifications
<?php
// File: includes/hooks/campaign-notifications.php
add_hook('CompleteBroadcast', 1, function($vars) {
$campaignId = $vars['campaign_id'] ?? null;
if (!$campaignId) {
return;
}
$campaign = \App\Models\Campaign::find($campaignId);
$user = $campaign->user;
// Send notification
$user->notify(new CampaignCompletedNotification($campaign));
// Log completion
Log::info("Campaign {$campaignId} completed", [
'sent' => $campaign->sent_count,
'bounced' => $campaign->bounce_count,
'duration' => $campaign->getDuration()
]);
});
Example 4: Custom Validation
<?php
// File: includes/hooks/validation.php
add_hook('AddContact', 1, function($vars) {
$email = $vars['email'] ?? '';
// Block disposable email domains
$disposableDomains = ['tempmail.com', 'throwaway.com', 'fakeinbox.com'];
$domain = substr(strrchr($email, "@"), 1);
if (in_array($domain, $disposableDomains)) {
Log::warning("Blocked disposable email: {$email}");
throw new Exception('Disposable email addresses are not allowed');
}
});
Debugging Tips
-
Log everything during development:
add_hook('AddContact', 1, function($vars) {
Log::debug('AddContact hook fired', $vars);
}); -
Use descriptive function names:
function mycompany_contacts_sync_to_hubspot($vars) { ... } -
Check the queue for background hooks:
php artisan queue:work --once -
Monitor the Laravel log:
tail -f storage/logs/laravel.log