While Converge has a highly customizable UI through themes, it also allows you to inject views at specific points during the rendering process. View interceptors give you this flexibility—you can register views or hooks at predefined view locations. This is especially useful when adding UI elements like cards (e.g., Carbon Ads) or badges to specific items in the sidebar.
To register a new view interceptor, call the intercept() method from the module provider. It accepts two arguments:
Interceptor enum).use Converge\Module; use Converge\Enums\Interceptor; use Illuminate\Contracts\View\View; public function module(Module $module): Module { return $module // ... ->intercept(Interceptor::BODY_START, function (): View { return view('banners.featured-sponsors'); }); }
Converge makes view injection more powerful by providing context at most interception point (not all), allowing you to render views conditionally. For example, to inject content only when a sidebar item is active (e.g., the topic being viewed), you can do:
use Converge\Module; use Converge\Enums\Interceptor; use Illuminate\Contracts\View\View; use Converge\Sidebar\SidebarItem; public function module(Module $module): Module { return $module // ... ->intercept(Interceptor::AFTER_SIDEBAR_ITEM, function (SidebarItem $item): View|string|null { if ($item->isActive()) { return '<span class="badge">Active</span>'; // or svg('icon-name') etc. } return null; }); }
This feature unlocks powerful UI customizations, such as adding badges, icons, or additional markup based on the current rendering context.
when injecting some views you may re build the assets again using:
php artisan converge:build
you may keep watching changes by using :
php artisan converge:build --watch
These interception points give you access to the SidebarItem instance:
Interceptor::BEFORE_SIDEBAR_LINK — Before the sidebar linkInterceptor::AFTER_SIDEBAR_LINK — After the sidebar linkInterceptor::BEFORE_SIDEBAR_LABEL — Before the sidebar labelInterceptor::AFTER_SIDEBAR_LABEL — After the sidebar labelYou can use the methods provided by SidebarItem to tailor the output as needed.
use Illuminate\Contracts\View\View; use Converge\Sidebar\SidebarItem; ->intercept(Interceptor::AFTER_SIDEBAR_ITEM, function (SidebarItem $item): View|string|null { $item->isActive(); // check if current sidebar is the active one $item->getLabel(); // eg : view interceptors $item->getSort(); // eg: 4, (reset to 0 in every group) $item->getDepth(); // eg: 1 $item->getUrl(); // eg: /docs/modules/view-interceptors });
These interception points are related to sidebar groups and provide access to the SidebarGroup instance:
Interceptor::BEFORE_SIDEBAR_GROUP_LABEL — Before the sidebar group labelInterceptor::AFTER_SIDEBAR_GROUP_LABEL — After the sidebar group labelInterceptor::BEFORE_SIDEBAR_GROUP_ITEMS — Before the sidebar group itemsInterceptor::AFTER_SIDEBAR_GROUP_ITEMS — After the sidebar group itemsYou can use the methods provided by SidebarItem to tailor the output as needed.
use Illuminate\Contracts\View\View; use Converge\Sidebar\SidebarItem; ->intercept(Interceptor::AFTER_SIDEBAR_ITEM, function (SidebarItem $item): View|string|null { $item->getLabel(); // eg : modules $item->getSort(); $item->getDepth(); $item->getUrl(); // eg: /docs/modules $item->hasActiveChild(); // @todo });
Interceptor::BEFORE_SIDEBAR_CLUSTERSInterceptor::AFTER_SIDEBAR_CLUSTERSno context aware available
Interceptor::SIDEBAR_STARTInterceptor::BEFORE_SIDEBAR_ITEMSInterceptor::AFTER_SIDEBAR_ITEMSInterceptor::SIDEBAR_ENDno context aware available
Interceptor::HEAD_STARTInterceptor::HEAD_ENDThese are particularly useful for injecting scripts like analytics tools (e.g., Google Analytics).
You can place your analytics script in a Blade component for clean reuse. For example:resources/views/components/analytics/gtags.blade.php :
@production <!-- gtags --> @if (config('services.google.analytics_id')) <script async src="https://www.googletagmanager.com/gtag/js?id={{ config('services.google.analytics_id') }}"></script> <script> window.dataLayer = window.dataLayer || []; function gtag() { dataLayer.push(arguments); } gtag('js', new Date()); gtag('config', '{{ config('services.google.analytics_id') }}'); </script> @endif @endproduction
You can register the component in a specific module or globally via a service provider:
/** * Bootstrap any application services. */ public function boot(): void { app(ViewInterceptor::class) ->registerViewInterceptor(Interceptor::HEAD_END, fn() => view('components.analytics.gtags')); }
Other points coming soon...