Skip to main content

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:

ParameterTypeDescription
$hookstringThe name of the hook to attach to
$priorityintExecution order (lower numbers run first)
$functioncallableThe 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​

  1. Log everything during development:

    add_hook('AddContact', 1, function($vars) {
    Log::debug('AddContact hook fired', $vars);
    });
  2. Use descriptive function names:

    function mycompany_contacts_sync_to_hubspot($vars) { ... }
  3. Check the queue for background hooks:

    php artisan queue:work --once
  4. Monitor the Laravel log:

    tail -f storage/logs/laravel.log