Analytics - Google - v1.0.0
Date Ranges
ArtisanPackUI\AnalyticsGoogle\Reporting\DateRange is an immutable value object wrapping a startDate / endDate pair in the format the GA4 Data API expects: YYYY-MM-DD or a GA4 alias like today, yesterday, or NdaysAgo.
Factories
DateRange::lastDays()
public static function lastDays( int $days ): self
Build a range covering the last N days ending today. Uses GA4's NdaysAgo alias so no local clock skew is possible.
DateRange::lastDays( 30 );
// startDate: "29daysAgo", endDate: "today"
Throws InvalidArgumentException when $days < 1. Clamps to DateRange::MAX_DAYS (730, roughly two years — the standard GA4 retention window) on the high end.
DateRange::between()
public static function between( DateTimeInterface|string $start, DateTimeInterface|string $end ): self
Build a range from explicit start and end dates. DateTimeInterface inputs get formatted with Y-m-d; strings pass through, so aliases work too.
DateRange::between( now()->subMonth(), now() );
DateRange::between( '2026-01-01', '2026-01-31' );
DateRange::between( 'yesterday', 'today' );
Direct construction
new DateRange( startDate: '2026-01-01', endDate: '2026-01-31' );
new DateRange( startDate: '7daysAgo', endDate: 'yesterday' );
The constructor guards both values against the accepted formats and throws InvalidArgumentException at construction time on bad input — you get a stack trace at the caller, not deep inside a Data API response parser.
Accepted formats
- Calendar dates:
YYYY-MM-DD. Parsed viaIlluminate\Support\Carbon::parse()so any Carbon-parseable string works, but stick toYYYY-MM-DDfor portability. - GA4 relative aliases:
today,yesterday, orNdaysAgowhereNis a positive integer. Case-insensitive.
Any other input throws InvalidArgumentException.
toArray()
public function toArray(): array
Serializes to the shape the runReport dateRanges array expects:
DateRange::lastDays( 7 )->toArray();
// [ 'startDate' => '6daysAgo', 'endDate' => 'today' ]
Constants
DateRange::MAX_DAYS = 730— the upper boundlastDays()clamps to. Also used by the Livewire components and HTTP controllers to clamp caller-supplieddaysparameters so a user can't force multi-decade lookups on everywire:poll.