Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Google Ads Laravel Package

spotonlive/laravel-google-ads

A Laravel wrapper for the Google Ads API that simplifies authentication and lets you manage campaigns, ad groups, ads, and reporting from your PHP application. Includes configuration, service provider, and facade integration for quick setup.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install and discover. composer require spotonlive/laravel-google-ads. On Laravel 5.5+ the service provider and GoogleAds facade are auto-discovered; on older apps register SpotonLive\GoogleAds\GoogleAdsServiceProvider in config/app.php and alias the facade manually.
  2. Publish the config first. Run php artisan vendor:publish --provider="SpotonLive\GoogleAds\GoogleAdsServiceProvider" and open config/google-ads.php. This is the single source of truth for credentials and API settings — read it before reading any package source.
  3. Populate credentials. Set the client ID, client secret, developer token, refresh token, and (for manager accounts) the login-customer-id via env vars referenced in the config, then php artisan config:clear. Keep secrets out of the repo.
  4. Find the bound client. Inspect the service provider to see which class the facade resolves to — that class exposes the query/reporting methods. The README describes the intent ("query campaigns, ad groups, performance data") but the exact method names live in src/.
  5. Prove it with a read-only query. Start with a single campaign report for a test account: resolve the facade, point it at one customer ID (numbers only, no dashes), and run a GAQL SELECT campaign.id, campaign.name, metrics.clicks FROM campaign. Confirm you get rows before wiring anything into your app.

The first real use case is almost always "campaign performance for the last N days" — get that working end-to-end in a tinker session before building around it.

Implementation Patterns

Wrap the facade behind your own service. Don't scatter GoogleAds:: calls through controllers. Create a GoogleAdsReportService (or repository) that takes the facade/client via constructor injection and returns your own DTOs or collections. This insulates the rest of the app from the package's nested response arrays and makes it trivial to swap the implementation if the wrapper goes stale.

One client, many customer IDs. Credentials are configured once, but the target account varies per call. Pass the customer ID explicitly at call time, and set login-customer-id in config when you operate through an MCC. Treat customer IDs as strings everywhere (they can exceed 32-bit ints).

Keep GAQL in dedicated classes/constants. Store query strings in App\GoogleAds\Queries\* classes or constants rather than inlining multi-line strings in jobs. You'll reuse and diff them far more than you expect, and Google Ads requires field/segment compatibility that's easier to reason about in isolation.

Cache reports, don't hammer the API. Reporting data changes slowly. Key a cache entry by sha1($gaql . $customerId . $dateRange) with a 15–60 minute TTL, and warm it from a scheduled command (php artisan ads:warm-reports) so user requests hit cache instead of the API. This also smooths over quota limits.

Run heavy pulls in queued jobs. Large SearchStream-style reports belong in a job, not a request. Map rows into an Eloquent table (ads_campaign_daily) so dashboards query your DB, not Google. Schedule the job nightly.

Normalize Google's shapes immediately. Metrics like cost_micros and nested campaign/ad_group objects should be flattened into your DTOs at the boundary. Downstream code should never see $row['metrics']['costMicros'].

Testing. Mock the facade (GoogleAds::shouldReceive(...)->andReturn(...)) or swap the resolved instance in the container. Reset the facade/container between tests so singletons don't leak state. For integration tests use a dedicated test customer ID and gate them behind an env flag.

Gotchas and Tips

  • Maintenance is the headline risk. Last release was April 2022. Google Ads API versions are sunset roughly yearly and the underlying google-ads-php dependency must track them. Before committing, check composer.json for the pinned Google Ads library version and confirm that API version is still live. On modern PHP/Laravel you may need a fork, a version bump, or to bypass the wrapper and call googleads/google-ads-php directly. Budget for this — it's the difference between "quick integration" and "abandoned dependency."
  • Config caching bites. The provider reads config at boot. After changing credentials or login-customer-id, run php artisan config:clear (and config:cache in deploy scripts) or you'll debug a ghost.
  • Refresh tokens expire. If the OAuth consent screen is still in "Testing" mode, refresh tokens expire in ~7 days. Publish the app or set the correct consent-screen status, and handle invalid_grant gracefully.
  • Developer token approval. Test accounts work with a test token; production needs an approved developer token. Expect DEVELOPER_TOKEN_NOT_APPROVED / AUTHORIZATION_ERROR until then. These are account-setup errors, not code bugs.
  • Customer IDs and manager accounts. Strip dashes, keep as string, and remember login-customer-id is mandatory when operating under an MCC — omitting it yields auth errors that look like permission problems.
  • Quotas and backoff. You will hit RESOURCE_EXHAUSTED. Implement exponential backoff and prefer batched/streaming reads and cached results over tight loops.
  • Micros and time zones. Divide *_micros by 1,000,000 for currency. Reporting dates are in the account's time zone, not your app's — don't mix segments.date with UTC assumptions.
  • Debugging. Enable the underlying library's logging/HTTP log and log the GAQL plus any request ID per call; Google support asks for it. Turn it off in production.
  • Extension point. If you need retries, structured logging, or metrics around calls, subclass the resolved client and rebind it in a small service provider ($this->app->bind(...)) rather than editing vendor code.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource