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