arout / seo-toolkit-pro
There is no license information available for the latest version (v1.0.6) of this package.
Pro tier for arout/seo-toolkit: on-page audit dashboard, readability scoring, 404 monitor, redirect manager, internal linking suggestions, and analytics tag manager.
Package info
github.com/arout77/SEO-Toolkit-Pro
Type:rhapsody-module
pkg:composer/arout/seo-toolkit-pro
v1.0.6
2026-10-05 00:38 UTC
Requires
- php: >=8.4
- arout/seo-toolkit: ^1.0
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Pro tier for arout/seo-toolkit. Depends on it via Composer; ships as its
own module rather than a license-flag inside Core.
Features
- On-page audit dashboard — title/meta-description length, H1 count, image alt coverage, canonical presence, per crawled page.
- Readability analysis — Flesch Reading Ease score per page.
- 404 monitor — every real 404 hit logged (URL, referrer, IP, UA, timestamp), aggregated on display, one-click promote to a redirect.
- Redirect manager — 301/302 table, matched before falling through to a real 404.
- Internal linking suggestions — keyword-overlap between page title/meta-description (deliberately the simple version — full content-similarity is a future upgrade, no content/tagging model exists in Rhapsody yet to build a stronger version on).
- Analytics tag manager — GA4, Meta Pixel, and a generic custom-script field, injected via a Twig function themes opt into explicitly.
Setup
composer require arout/seo-toolkit-pro- Run
php rhapsody module:install arout/seo-toolkit-pro, which runsModuleProvider::install()— creates the module's four tables. - Add
{{ mod_seo_toolkit_pro_seo_analytics_scripts()|raw }}near</head>in every theme layout you want analytics tags to appear on — same opt-in pattern as{{ schema_markup|raw }}. Note the long name:TwigFacade::addFunction()auto-prefixes every registered function withmod_{slug}_, so the bareseo_analytics_scripts()name used inModuleProviderisn't what's actually callable from a template. - Current URL prefix is
/arout-seo-toolkit-pro/..., not/seo-toolkit-pro/.... Routes register under the module's vendor-joined slug for now — a fix to use the package-only slug instead is planned but not yet applied (tracked as its own phase in the module-rendering work, since it needs a collision-prevention mechanism first). Every path in this module will need updating when that lands. Visit/arout-seo-toolkit-pro/settingsto configure GA4 / Meta Pixel / custom script,/arout-seo-toolkit-pro/sample-urlsto register concrete URLs for parameterized routes, then/arout-seo-toolkit-pro/auditand hit "Run Scan".
What's still assumed, not confirmed
Everything below is flagged inline with NOTE: comments at the point it's
used. A lot of what was originally guessed here has since been confirmed
against real pasted source and corrected — what's left:
ModuleContext's own facade methods beyonddatabase()andtwig()(both now fully confirmed) —events(),routes(),settings()haven't individually been checked against source, only inferred from working behavior.RouteNotFoundevent — confirmed to implementStoppableEventInterfacewithsetResponse(Response)to stop propagation. Still assumed: that it also exposesgetRequest().- The crawler's internal request dispatch (
RouteCrawler::render()) — still assumesRequest::createInternal()and a container-resolvedRouter::dispatch()exist for firing a request without going over real HTTP. Untested so far since nothing has actually triggered a scan yet. routes()->registered()'s shape — assumed['method' => ..., 'path' => ...]rows, mirroring Core SEO Toolkit's sitemap generator.- The global
redirect()helper — assumed to exist as a bare global function,redirect(string $path): Response. Used now inProDashboardController::redirectWithFlash(). - Flash messages — rather than guess an unconfirmed
Session::flash()signature,redirectWithFlash()sets$_SESSION['flash_success']/$_SESSION['flash_error']directly — the exact keys already confirmed live inBaseController.php. Should behave identically to whateverSession::flash()does internally if that's a thin wrapper over the same two keys; if there's more to it (expiry timing, structured data), this needs revisiting.
Confirmed and fixed this round
TwigFacade(Rhapsody\Core\Modules\Facades\TwigFacade) hasaddExtension(ExtensionInterface $extension)andaddFunction(string $name, callable $callback, array $options = [])— notextensions()/functions()as originally guessed.ModuleProvider::boot()now callsaddFunction()correctly.ProDashboardController'sview()/redirect()were placeholder stubs returning a plain array —Router::execute()requires a realRhapsody\Core\Response, which is why every dashboard route 500'd with aTypeErroronce the routing-prefix issue was fixed.view()now callsTwigFacade::render($template, $data): Response; redirects go through the assumed globalredirect()helper plus the direct$_SESSIONflash-key writes described above.- Admin templates now extend
layouts/main.twig, not_layout.twigorlayouts/admin.twig(both tried and both wrong). The real path is confirmed from this project's own theme-submission requirements:views/themes/<theme_name>/layouts/main.twig, required to definetitle,description,styles,head_extensions,navigation,content,scriptsblocks. Onlycontentis overridden here, which is fine — Twig inheritance only requires overriding blocks you want to customize. ProDashboardController::view()now also supplies ametaarray (meta.title/meta.description) in the data passed toTwigFacade::render().main.twig's defaulttitle/descriptionblocks render{{ meta.title }}/{{ meta.description }}, and the confirmed app convention is that$this->view(...)normally receives page meta as a third argument —TwigFacade::render()doesn't do that wrapping yet (explicitly deferred to Phase 5 in the module-rendering work), soview()builds the samemetashape manually here instead, pre-empting a possible undefined-variable error in the layout rather than waiting to hit it.TwigFacade::render()doesn't auto-append.twig— it only does'@' . $this->slug . '/' . $view, nothing more, confirmed directly from source. Every$this->view('admin/xxx', ...)call inProDashboardControllernow passes the fulladmin/xxx.twigfilename.- Views directory moved from
resources/views/toviews/. A debug dump ofTwigFacade's real constructor showed the module loader computes each module's Twig path as<install path>/views, not<install path>/resources/views— the opposite of what had previously been logged as confirmed (that earlier conclusion didn't actually hold up against a live boot).TwigFacade.phpitself is correct and was never the problem; this was purely a wrong assumption about a sibling class's path-building logic. All five admin templates now live underviews/admin/at the package root.