Google Search Console - v1.0.0
Google Search Console Changelog
[Unreleased]
[1.0.0] - 2026-07-11
Initial release. Search Console performance data and drop-in UI components on top of the shared artisanpack-ui/google OAuth2 + token management layer.
Added
SearchAnalyticsClient— typed wrapper over Google'ssearchAnalytics.queryendpoint, with per-connection-per-query cache keys, config-driven timeout (guards against Guzzle'stimeout(0)= "no timeout" footgun), and well-typed exceptions (BaseNotInstalledException,ReportingException).- Three high-level fetchers:
PerformanceOverviewFetcher— two queries (totals + daily trend).hasDatadistinguishes "empty" from "all zeros" so fresh properties don't render misleading zero-metric cards.TopQueriesFetcher— top queries by clicks.DEFAULT_LIMIT = 50.TopPagesFetcher— top pages by clicks.DEFAULT_LIMIT = 50.
- Typed value objects —
DateRange,SearchAnalyticsRequest,SearchAnalyticsResponse,PerformanceOverviewData,TopQueriesData,TopPagesData. Every DTO exposes atoArray()matching the HTTP endpoints' JSON shape. - Three Livewire components —
PerformanceCard,TopQueriesTable,TopPagesTable. Auto-registered undergoogle-search-console::*aliases when Livewire is installed. Handle missing-base state, unconnected state, empty state, and API errors uniformly. - Three React components —
PerformanceCard,TopQueriesTable,TopPagesTable. Ship as source underresources/js/react/. Use a shared TypeScript fetch client (resources/js/shared/) so both React and Vue talk to the same server payload shape. - Three Vue 3 components — mirror the React API.
resources/js/vue/. - Three JSON HTTP endpoints backing the React and Vue components —
GET /performance,GET /top-queries,GET /top-pages. Mounted under a configurable prefix (default/google-search-console) withweb+authmiddleware. Deliberately ignore any user-supplied?site_urloverride so tenants can't cross-query. - OAuth scope contribution —
webmasters.readonlyis contributed to the baseartisanpack-ui/googlepackage's sharedScopeRegistryvia theap.google.scopesfilter hook. Single consent screen covers Search Console alongside every other Google service. - Optional CMS framework bridge — three widget wrappers (
PerformanceCardWidget,TopQueriesTableWidget,TopPagesTableWidget) undersrc/Bridges/CmsFramework/AdminWidgets/that register withartisanpack-ui/cms-framework'sAdminWidgetManagerwhen the framework is installed. Each wrapper extends its underlying Livewire component and implementsAdminWidgetInterface, so shipped views + styles carry through to CMS-hosted widgets. Widget-type map exposed asGoogleSearchConsoleServiceProvider::cmsFrameworkWidgetTypeMap()for testability. Bridge is dormant when either dependency is absent. CmsFrameworkInstalledsupport class — presence detector mirroringBaseInstalled(memoised per-process, resettable in tests,setForTesting()for controlled state).BaseInstalledsupport class — memoised detector forartisanpack-ui/google.GoogleConnectionResolver— user → connectedGoogleConnectionmapping. Rebindable per tenant.- Cache layer —
SearchAnalyticsClientcaches successful responses via Laravel's default cache store (google-search-console.reporting.cache_ttlseconds, default300). Per-connection, per-query cache keys prevent cross-tenant contamination. - Publishable assets —
google-search-console-config,google-search-console-views,google-search-console-js. - Comprehensive test suite — 61 tests across
SearchAnalyticsClient, fetchers, controllers, Livewire component rendering (mount, empty state, sort order, pagination, missing-base state), and the CMS bridge (using local stubs autoloaded into the real cms-framework namespace so the bridge is exercised without pulling in the framework's transitive deps). - Comprehensive
/docstree — installation, components (Livewire / React / Vue / custom), HTTP endpoints, reporting API, scopes, CMS bridge, API reference, testing, FAQ, troubleshooting. - Laravel 10, 11, 12, and 13 support via widened
illuminate/supportconstraint. - CI + Release workflows — GitHub Actions matrix testing PHP 8.2/8.3/8.4 × Laravel 12/13, plus a tag-driven release workflow with Packagist push.
Security
- Controllers ignore any user-supplied
?site_urlquery string. The site URL comes from config only — accepting a caller-supplied override would let one authenticated user query any property the shared Google account owns. - Cache keys hash the connection ID + query payload so distinct users cannot see each other's cached rows.
- The
SearchAnalyticsClienttimeout falls back to 30 seconds when the config value isnull/0/ non-numeric — a stray unset env var can't hang the worker on a stuck endpoint.
Notes
- No new database migrations. All persisted data (
google_connectionstokens) lives in the base package's tables. - No secrets stored by this package.
GSC_SITE_URLis public information.