Google Search Console - v1.0.0
DateRange
Immutable value object describing an inclusive [startDate, endDate] window. Used by every fetcher and by SearchAnalyticsRequest to build the startDate / endDate fields of the Search Console API payload.
FQCN: ArtisanPackUI\GoogleSearchConsole\Reporting\DateRange.
Constructor
new DateRange(
public readonly string $startDate,
public readonly string $endDate,
)
Both dates are ISO 8601 (YYYY-MM-DD). Inclusive on both ends — new DateRange('2026-01-01', '2026-01-28') covers 28 days.
Constants
DateRange::MAX_DAYS = 480— Google's practical upper bound. Search Console has ~16 months of data. Ranges overMAX_DAYStruncate on Google's side.
Static constructors
DateRange::lastDays( int $days ): self
The most common shape — a rolling window ending on today's date. Google typically finalises data 2–3 days behind, so recent days may still show low or zero values.
DateRange::lastDays( 28 ); // last 28 days
DateRange::lastDays( 7 ); // last week
DateRange::lastDays( 480 ); // max
DateRange::between( DateTimeInterface|string $start, DateTimeInterface|string $end ): self
An explicit window. Accepts either PHP DateTime / Carbon instances or ISO strings.
DateRange::between( '2026-01-01', '2026-01-31' );
DateRange::between( Carbon::parse( '2026-01-01' ), Carbon::parse( '2026-01-31' ) );
Usage
Fetchers take a DateRange directly:
use ArtisanPackUI\GoogleSearchConsole\Reporting\DateRange;
$fetcher->fetch( $connection, DateRange::lastDays( 28 ) );
SearchAnalyticsRequest too:
use ArtisanPackUI\GoogleSearchConsole\Reporting\SearchAnalyticsRequest;
new SearchAnalyticsRequest(
dateRange: DateRange::between( '2026-01-01', '2026-01-31' ),
dimensions: [ 'query' ],
);
Serialization
DateRange is serialized to the API payload via SearchAnalyticsRequest::toApiPayload():
[
'startDate' => $this->dateRange->startDate, // 'YYYY-MM-DD'
'endDate' => $this->dateRange->endDate, // 'YYYY-MM-DD'
// dimensions, filters, rowLimit, startRow, type, dataState conditionally appended
]
The strings ship verbatim — no reformatting or timezone conversion. Both dates are interpreted by Google in UTC.
Common pitfalls
- Off-by-one on the trailing day. Search Console's most recent 2–3 days are usually incomplete.
DateRange::lastDays(7)includes today, which may show as zero. If you want "the last week of final data", subtract 3:DateRange::between( today()->subDays(9), today()->subDays(3) ). - Ranges over 16 months. Google returns rows only for dates where data exists — a
DateRangespanning years beyond the Search Console retention window quietly returns zero rows for the missing days. - Timezone. Both dates are treated as UTC calendar days by Google. If your app's timezone is Pacific and you build a range from
now()->toDateString(), you may include or exclude a day the user thinks is "today".
Testing
Deterministic; no side effects. Use it directly in tests:
use ArtisanPackUI\GoogleSearchConsole\Reporting\DateRange;
it( 'lastDays returns an inclusive range', function () {
$range = DateRange::lastDays( 7 );
expect( $range->startDate )->toBeString();
expect( $range->endDate )->toBeString();
expect( $range->endDate >= $range->startDate )->toBeTrue();
} );