Skip to main content

Output Hooks Reference

Output hooks allow you to inject custom HTML, CSS, JavaScript, and other content into specific locations within the Mumara Campaigns interface. Unlike module hooks that respond to events, output hooks render content when pages are displayed.

How Output Hooks Work

Output hooks return content that gets concatenated and rendered at specific locations:

add_hook('HeadTop', 1, function($vars) {
return '<link rel="stylesheet" href="/my-styles.css">';
});

To retrieve the combined output from all callbacks registered to an output hook:

// In a Blade template
{!! hook_get_output('HeadTop', $vars) !!}

Available Context Variables

Output hooks receive a $vars array containing useful context:

add_hook('HeadTop', 1, function($vars) {
// Common variables available:
// $vars['route'] - Current route name
// $vars['user'] - Authenticated user object
// $vars['request'] - Current request object

return '<meta name="page" content="' . ($vars['route'] ?? 'unknown') . '">';
});

Document Head Hooks

HeadTop

Renders at the very top of the <head> section, before any other elements.

add_hook('HeadTop', 1, function($vars) {
return '<meta charset="UTF-8">';
});

Best For:

  • Character encoding declarations
  • Early meta tags
  • Preconnect/preload hints

Example - Add Preconnect for External Resources:

add_hook('HeadTop', 1, function($vars) {
return <<<HTML
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://cdn.example.com" crossorigin>
HTML;
});

HeadEnd

Renders at the end of the <head> section, just before the closing </head> tag.

add_hook('HeadEnd', 1, function($vars) {
return '<link rel="stylesheet" href="/custom/theme.css">';
});

Best For:

  • Custom stylesheets
  • Additional meta tags
  • Favicon overrides
  • Third-party CSS libraries

Example - Load Custom CSS Based on Route:

add_hook('HeadEnd', 1, function($vars) {
$route = $vars['route'] ?? '';
$css = '';

if (str_starts_with($route, 'campaigns.')) {
$css .= '<link rel="stylesheet" href="/css/campaigns-custom.css">';
}

if (str_starts_with($route, 'contacts.')) {
$css .= '<link rel="stylesheet" href="/css/contacts-custom.css">';
}

return $css;
});

Document Body Hooks

BodyTop

Renders immediately after the opening <body> tag.

add_hook('BodyTop', 1, function($vars) {
return '<div id="page-loader" class="loading"></div>';
});

Best For:

  • Loading indicators
  • No-JavaScript fallbacks
  • Body-level wrapper elements
  • Skip navigation links (accessibility)

Example - Add Accessibility Skip Link:

add_hook('BodyTop', 1, function($vars) {
return '<a href="#main-content" class="skip-link">Skip to main content</a>';
});

BodyEnd

Renders just before the closing </body> tag.

add_hook('BodyEnd', 1, function($vars) {
return '<script src="/custom/app.js"></script>';
});

Best For:

  • JavaScript files
  • Analytics scripts
  • Chat widgets
  • Deferred scripts

Example - Add Google Analytics:

add_hook('BodyEnd', 1, function($vars) {
$trackingId = config('services.google.analytics_id');

if (!$trackingId) {
return '';
}

return <<<HTML
<script async src="https://www.googletagmanager.com/gtag/js?id={$trackingId}"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '{$trackingId}');
</script>
HTML;
});

PrimaryMenu

Allows adding items to the primary sidebar navigation menu.

add_hook('PrimaryMenu', 1, function($vars) {
return '<li class="nav-item"><a href="/custom-page" class="nav-link">Custom Page</a></li>';
});

Best For:

  • Adding custom menu items
  • Injecting addon navigation
  • User-specific menu options

Example - Add Conditional Menu Item:

add_hook('PrimaryMenu', 1, function($vars) {
$user = $vars['user'] ?? null;

if (!$user || !$user->hasPermission('view_reports')) {
return '';
}

return <<<HTML
<li class="kt-menu__item">
<a href="/custom-reports" class="kt-menu__link">
<span class="kt-menu__link-icon">
<i class="fas fa-chart-bar"></i>
</span>
<span class="kt-menu__link-text">Custom Reports</span>
</a>
</li>
HTML;
});

TopNav

Renders content in the top navigation bar area.

add_hook('TopNav', 1, function($vars) {
return '<div class="top-nav-item">Custom Element</div>';
});

Best For:

  • Custom top bar elements
  • Quick action buttons
  • Status indicators

Allows customization of breadcrumb navigation.

add_hook('BreadcrumbNav', 1, function($vars) {
$route = $vars['route'] ?? '';

if ($route === 'list.index') {
return <<<HTML
<div class="kt-subheader__breadcrumbs">
<a href="/dashboard" class="kt-subheader__breadcrumbs-link">Dashboard</a>
<span class="kt-subheader__breadcrumbs-separator"></span>
<span class="kt-subheader__desc">Contact Lists</span>
</div>
HTML;
}

return '';
});

Best For:

  • Custom breadcrumb structures
  • Dynamic breadcrumb content
  • Route-specific navigation

Page Section Hooks

alerts

Renders alert messages in the main content area.

add_hook('alerts', 1, function($vars) {
return '<div class="alert alert-info">System update available.</div>';
});

Best For:

  • System-wide alerts
  • Warning messages
  • Transactional limit notifications

Example - Show Sending Limit Warning:

add_hook('alerts', 1, function($vars) {
$user = auth()->user();

if (!$user) {
return '';
}

$dailyLimit = $user->daily_limit ?? 10000;
$sentToday = \App\Models\CampaignScheduleLog::where('user_id', $user->id)
->whereDate('created_at', today())
->count();

if ($sentToday < $dailyLimit * 0.8) {
return '';
}

$remaining = $dailyLimit - $sentToday;

return <<<HTML
<div class="alert alert-warning">
<strong>Sending Limit:</strong> You have {$remaining} emails remaining for today.
</div>
HTML;
});

AlertBar

Renders alert messages at the top of the page content area, below the navbar.

add_hook('AlertBar', 1, function($vars) {
return '<div class="alert alert-info">System maintenance scheduled for tonight.</div>';
});

Best For:

  • System announcements
  • Maintenance notices
  • Feature announcements

Example - Show Maintenance Warning:

add_hook('AlertBar', 1, function($vars) {
$maintenanceTime = config('app.maintenance_scheduled');

if (!$maintenanceTime) {
return '';
}

$timeFormatted = \Carbon\Carbon::parse($maintenanceTime)->format('M j, Y g:i A');

return <<<HTML
<div class="alert alert-warning alert-dismissible fade show" role="alert">
<strong>Scheduled Maintenance:</strong> The system will be briefly unavailable on {$timeFormatted}.
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
HTML;
});

TitleBar

Renders in the page title bar area, typically for adding descriptions or badges.

add_hook('TitleBar', 1, function($vars) {
$route = $vars['route'] ?? '';

if ($route === 'list.index') {
return <<<HTML
<div class="pagetitle">
<h4>Contact Lists</h4>
<p>Manage your contact lists, import contacts, and organize your audience.</p>
</div>
HTML;
}

return '';
});

Best For:

  • Page descriptions
  • Status badges
  • Quick action buttons

ContentEnd

Renders at the end of the main content area, before the footer.

add_hook('ContentEnd', 1, function($vars) {
return '<div class="content-footer">Additional content here</div>';
});

Best For:

  • Related content sections
  • Call-to-action blocks
  • Content footers

Renders in the page footer section.

add_hook('Footer', 1, function($vars) {
return '<p>Custom footer content</p>';
});

Best For:

  • Copyright notices
  • Footer links
  • Support information
  • Version numbers

Example - Add Version Info to Footer:

add_hook('Footer', 10, function($vars) {
$version = config('app.version', '1.0.0');

return <<<HTML
<div class="footer-version text-muted">
<small>Version {$version}</small>
</div>
HTML;
});

Page-Specific Hooks

addPageHtml

A versatile hook for adding content to specific pages. Often used with route checking.

add_hook('addPageHtml', 1, function($vars) {
$route = $vars['route'] ?? '';

// Only add content on the dashboard
if ($route !== 'dashboard') {
return '';
}

return '<div class="dashboard-widget">Custom Widget</div>';
});

Example - Add Help Widget to Specific Pages:

add_hook('addPageHtml', 5, function($vars) {
$route = $vars['route'] ?? '';

$helpContent = [
'campaigns.create' => 'Need help creating a campaign? Check our guide.',
'contacts.import' => 'Importing contacts? Make sure your CSV is properly formatted.',
'settings.smtp' => 'Configure your SMTP settings for optimal deliverability.',
];

if (!isset($helpContent[$route])) {
return '';
}

$message = $helpContent[$route];

return <<<HTML
<div class="help-tip alert alert-light">
<i class="fas fa-lightbulb text-warning"></i> {$message}
<a href="/docs" target="_blank">Learn more</a>
</div>
HTML;
});

SocialLogin

Renders social login buttons on the login page.

add_hook('SocialLogin', 1, function($vars) {
return <<<HTML
<div class="social-login">
<a href="/auth/google" class="btn btn-google">
<i class="fab fa-google"></i> Sign in with Google
</a>
<a href="/auth/facebook" class="btn btn-facebook">
<i class="fab fa-facebook"></i> Sign in with Facebook
</a>
</div>
HTML;
});

Best For:

  • OAuth login buttons
  • Single Sign-On integration
  • Third-party authentication

Automation & Campaign Hooks

AutomationAddBlankJS

Injects JavaScript for the automation add blank page.

add_hook('AutomationAddBlankJS', 1, function($vars) {
return '<script>console.log("Automation page loaded");</script>';
});

AutomationChooseTemplateJS

Injects JavaScript for the template selection page.

add_hook('AutomationChooseTemplateJS', 1, function($vars) {
return '<script>// Custom template selection logic</script>';
});

AutomationCreateBroadcast

Renders content in the broadcast creation form.

add_hook('AutomationCreateBroadcast', 1, function($vars) {
return '<div class="custom-broadcast-options">Custom options</div>';
});

AutomationCreateBroadcastButtons

Adds custom buttons to the broadcast creation form.

add_hook('AutomationCreateBroadcastButtons', 1, function($vars) {
return '<button type="button" class="btn btn-secondary">Custom Action</button>';
});

AutomationPackageSettings

Renders custom package settings in the package creation form.

add_hook('AutomationPackageSettings', 1, function($vars) {
return <<<HTML
<div class="form-group">
<label>Custom Package Setting</label>
<input type="text" name="custom_setting" class="form-control">
</div>
HTML;
});

AutomationUserSettingsTab

Adds a custom tab to user settings.

add_hook('AutomationUserSettingsTab', 1, function($vars) {
return '<li class="nav-item"><a class="nav-link" data-toggle="tab" href="#custom-tab">Custom</a></li>';
});

AutomationUserSettings

Renders content in the user settings custom tab.

add_hook('AutomationUserSettings', 1, function($vars) {
return '<div class="tab-pane" id="custom-tab">Custom settings content</div>';
});

Domain & SMTP Hooks

SendingDomainPageTitleBar

Renders content in the sending domain page title bar.

add_hook('SendingDomainPageTitleBar', 1, function($vars) {
return '<span class="badge badge-info">Custom Badge</span>';
});

btn_sync_now

Renders a sync button on domain pages.

add_hook('btn_sync_now', 1, function($vars) {
return '<button class="btn btn-primary" onclick="syncDomain()">Sync Now</button>';
});

NodesListingPageOutput

Returns custom output for the SMTP nodes listing page.

add_hook('NodesListingPageOutput', 1, function($vars) {
// $vars contains nodes listing data
return '<div class="custom-nodes-content">Custom nodes view</div>';
});

sendingDomainEditPageOutput

Returns custom output for the sending domain edit page.

add_hook('sendingDomainEditPageOutput', 1, function($vars) {
// $vars contains domain data
return '<div class="custom-domain-content">Custom domain view</div>';
});

ContactListActions

Adds custom actions to the contact list actions dropdown.

add_hook('ContactListActions', 1, function($vars) {
// $vars contains list row data
$listId = $vars->id;

return <<<HTML
<a class="dropdown-item" href="/custom-action/{$listId}">
<i class="fas fa-cog"></i> Custom Action
</a>
HTML;
});

Controller-Based Output Hooks

Some hooks are used in controllers to get custom output:

AutomationChooseTemplate

Returns custom template selection output.

add_hook('AutomationChooseTemplate', 1, function($vars) {
// $vars contains:
// - type: Template type
// - user: User object
// - list: List data

return '<div class="custom-templates">Custom template selector</div>';
});

AutomationUserProfile

Returns custom user profile output.

add_hook('AutomationUserProfile', 1, function($vars) {
// $vars is the user ID
$userId = $vars[0];

return '<div class="custom-profile-section">Custom profile content</div>';
});

AutomationUpdateBroadcast

Returns custom output when updating a broadcast.

add_hook('AutomationUpdateBroadcast', 1, function($vars) {
// $vars contains broadcast update data
return '<div class="update-status">Broadcast updated successfully</div>';
});

TrackingVariables

Returns custom tracking variables for campaigns.

add_hook('TrackingVariables', 1, function($vars) {
// $vars contains campaign data
return 'custom_tracking_param=value';
});

Best Practices

1. Check Route Before Rendering

Don't inject content on every page if it's only needed on specific ones:

add_hook('addPageHtml', 1, function($vars) {
if (($vars['route'] ?? '') !== 'target.page') {
return '';
}
// Your content
});

2. Use Appropriate Priorities

  • 1-3: Critical content that must load first
  • 5-10: Standard content
  • 10+: Non-critical or dependent content

3. Minimize Inline Scripts

For larger scripts, load external files:

// Prefer this
return '<script src="/js/my-script.js"></script>';

// Over this (for large scripts)
return '<script>/* hundreds of lines */</script>';

4. Handle Missing Dependencies

add_hook('HeadEnd', 1, function($vars) {
// Only load if a condition is met
if (!config('features.custom_theme_enabled')) {
return '';
}

return '<link rel="stylesheet" href="/custom-theme.css">';
});

5. Escape User Data

Always escape user-provided data:

add_hook('TitleBar', 1, function($vars) {
$user = $vars['user'] ?? null;
$name = htmlspecialchars($user->name ?? 'Guest', ENT_QUOTES, 'UTF-8');

return "<span>Welcome, {$name}</span>";
});

6. Return Empty String When Not Applicable

Always return an empty string when no output is needed:

add_hook('AlertBar', 1, function($vars) {
if (!shouldShowAlert()) {
return ''; // Don't return null or void
}

return '<div class="alert">Message</div>';
});