Search by

electrictomcat / laravel-google-ads-conversions

electrictomcat

Drop-in offline conversion tracking for Laravel: captures GCLIDs from ad clicks, buffers conversions in cache, and uploads them to the Google Ads API.

Package info

github.com/electrictomcat/laravel-google-ads-conversions

Documentation

pkg:composer/electrictomcat/laravel-google-ads-conversions

Fund package maintenance!

electrictomcat

Statistics

Installs: 1 858

Dependents: 1

Suggesters: 0

Stars: 1

Open Issues: 0

v1.1.5 2026-11-05 07:49 UTC

This package is auto-updated.

Last update: 2026-11-05 16:44:01 UTC


README

Latest Version on Packagist License: MIT

Production-ready, drop-in offline conversion tracking for Laravel applications. Captures Google Ads click identifiers (gclid, gbraid, wbraid), buffers conversions in cache with zero database lag, and uploads them to the Google Ads API v17/v18.

โšก Need Meta CAPI, TikTok, LinkedIn, Microsoft Ads, or WooCommerce?

If you need multi-channel server-to-server tracking across Meta CAPI (v20.0), TikTok Events API, LinkedIn CAPI, Microsoft Advertising, an in-app live reporting dashboard, or turnkey WordPress & WooCommerce integration, check out OmniSignal Pro.

Key Features

  • ๐ŸŽฏ Full Click Attribution: Captures gclid (Search/Display) as well as gbraid and wbraid (iOS 14.5+ ATT app/web clicks) and maintains attribution across visitor sessions.
  • โšก One-Line Recording: Record conversions from anywhere โ€” controllers, Livewire, queued jobs, Eloquent observers (GoogleAdsConversions::record(...)).
  • ๐Ÿ‡ช๐Ÿ‡บ GDPR, ePrivacy & Consent Mode v2 Ready: Prior-consent cookie gating, automated 90-day retention pruning via Prunable, and explicit Google Consent Mode signals (ad_user_data, ad_personalization).
  • ๐Ÿ”’ Enhanced Conversions for Leads: Strict data minimization with SHA-256 hashed email & phone numbers.
  • ๐Ÿงช First-Class Testing Support: Built-in GoogleAdsConversions::fake() for easy test assertions in your application test suite.
  • ๐Ÿš€ High Performance & Safe Batching: Buffers in cache behind a sharded, lock-guarded dirty set, syncs to database, and uploads in batched requests of up to 2,000 conversions.
  • ๐Ÿ“ฆ Bring Your Own Model: Use the included Lead model or drop HasConversionsTrait onto your existing User, Visitor, or Order models.
  • ๐Ÿ› ๏ธ Artisan Tooling: Dedicated CLI commands for installing, testing credentials against live APIs, syncing cache, and running dry-run uploads.

Requires PHP 8.3+ and Laravel 11, 12, or 13.

Installation

composer require electrictomcat/laravel-google-ads-conversions

Publish configuration, database migrations, and run the interactive Google Ads OAuth & .env setup wizard:

php artisan google-ads:install

The installer will:

  1. Publish the config file and migrations.
  2. Prompt for your Google Cloud OAuth Client ID & Secret and generate a Google OAuth 2.0 authorization link (adwords and datamanager scopes).
  3. Exchange your authorization code (or use --listen to capture the local browser callback automatically) for a GOOGLE_ADS_REFRESH_TOKEN.
  4. Guide you to retrieve your GOOGLE_ADS_DEVELOPER_TOKEN and auto-discover your accessible GOOGLE_ADS_CUSTOMER_IDs.
  5. Inject the # Google Ads Offline Conversions credential section directly into your .env file.

๐Ÿ’ก You can re-run the credential setup wizard at any time with php artisan google-ads:install --setup (or php artisan google-ads:install --setup --listen to capture the browser callback automatically on http://127.0.0.1:8085).

Run migrations:

php artisan migrate

Configuration

If you prefer to configure your .env file manually, add the following section:

# Google Ads Offline Conversions
GOOGLE_ADS_DEVELOPER_TOKEN="your-developer-token"
GOOGLE_ADS_CLIENT_ID="your-client-id.apps.googleusercontent.com"
GOOGLE_ADS_CLIENT_SECRET="your-client-secret"
GOOGLE_ADS_REFRESH_TOKEN="your-refresh-token"
GOOGLE_ADS_CUSTOMER_ID="1234567890" # without hyphens
GOOGLE_ADS_LOGIN_CUSTOMER_ID=""      # optional Manager (MCC) account ID
GOOGLE_ADS_UPLOAD_API="data_manager" # "data_manager" (default) or "google_ads" (legacy)

Google Data Manager API (events:ingest) vs Legacy UploadClickConversions

Since June 15, 2026, Google requires new offline click conversion integrations to upload via the Google Data Manager API (https://datamanager.googleapis.com/v1/events:ingest).

  • data_manager (default): Uploads conversions via https://datamanager.googleapis.com/v1/events:ingest. Ensure the Data Manager API is enabled in your Google Cloud project and that your OAuth refresh token was authorized with the https://www.googleapis.com/auth/datamanager scope (automatically included when running php artisan google-ads:install --setup).
  • google_ads (legacy): Uses ConversionUploadService.UploadClickConversions for older integrations whose refresh tokens have not yet been re-authorized with the datamanager scope.

Re-queuing Conversions (ad-conversions:requeue)

To reset failed, rejected, or previously uploaded conversions back to pending so they can be re-uploaded:

# Reset failed and rejected conversions back to pending
php artisan ad-conversions:requeue

# Preview resetting conversions marked "uploaded" (dry run)
php artisan ad-conversions:requeue --status=uploaded --dry-run

# Reset conversions marked "uploaded" since a specific date and immediately re-upload
php artisan ad-conversions:requeue --status=uploaded --since="2026-06-15" --upload

Usage

1. Register the Click Capture Middleware & Exempt Cookies

In your bootstrap/app.php (Laravel 11+), register the middleware and exempt the package's attribution cookies from encryption so client-side JavaScript can read them:

use ElectricTomCat\GoogleAdsConversions\GoogleAdsConversions;
use ElectricTomCat\GoogleAdsConversions\Http\Middleware\CaptureGclid;

->withMiddleware(function (Middleware $middleware) {
    // Allow client-side scripts to read attribution cookies
    $middleware->encryptCookies(except: GoogleAdsConversions::cookieNames());

    $middleware->web(append: [
        CaptureGclid::class,
    ]);
})

2. Record a Conversion Event (Server-Side)

use ElectricTomCat\GoogleAdsConversions\Facades\GoogleAdsConversions;

// Basic lead conversion
GoogleAdsConversions::record('Contact Form');

// Conversion with value and currency
GoogleAdsConversions::record('Demo Booked', 250.00, 'USD');

// Conversion with order ID and Enhanced Conversions (hashed customer data)
GoogleAdsConversions::record(
    eventName: 'Purchase',
    value: 99.00,
    currency: 'USD',
    orderId: 'ORD-9821',
    userIdentifiers: [
        'email' => 'customer@example.com',
        'phone' => '+15551234567',
    ]
);

3. Client-Side JavaScript Tracking

Add the @googleAdsScript directive to your layout (e.g. before </head> or </body>):

@googleAdsScript

This injects the global window.trackGoogleAdsConversion(eventName, value, currency, orderId) helper. It inspects client cookies (google_ads_gclid, google_ads_gbraid, google_ads_wbraid) and dispatches the conversion via navigator.sendBeacon (falling back to fetch) to the package's built-in endpoint:

// Trigger a conversion from any frontend interaction or button click
window.trackGoogleAdsConversion('Add to Cart', 49.99, 'USD');

4. Navigation Micro-Conversions (Full-Page & SPA)

Track forward page navigation micro-conversions for ad-attributed visitors across full-page loads and SPA transitions (Livewire wire:navigate, Turbo, Inertia):

@googleAdsNavigationTracking

This directive only renders if the visitor has an active ad attribution (GoogleAdsConversions::hasAttribution()). It automatically posts navigation events (Page Navigation: /path) when visitors navigate forward.

5. Blade Directive for HTML Forms

Inject hidden click identifiers (gclid, gbraid, wbraid) into your contact or checkout forms:

<form action="/contact" method="POST">
    @csrf
    @googleAdsClickInputs

    <input type="text" name="name" required>
    <button type="submit">Submit</button>
</form>

6. Built-In Route Configuration

The package automatically exposes a route for client-side conversions (POST /api/google-ads/track-conversion, named google-ads-conversions.track). You can customize the route in config/google-ads-conversions.php:

'routes' => [
    'enabled' => true,
    'prefix' => 'api/google-ads',
    'middleware' => ['api'],
    'track_conversion_path' => 'track-conversion',
],

7. Testing with fake()

use ElectricTomCat\GoogleAdsConversions\Facades\GoogleAdsConversions;

public function test_booking_records_conversion(): void
{
    GoogleAdsConversions::fake();

    $this->post('/book', ['email' => 'test@example.com']);

    GoogleAdsConversions::assertRecorded('Demo Booked', 250.00);
    GoogleAdsConversions::assertNotRecorded('Other Event');
}

๐Ÿ’Ž Need Multi-Platform Tracking?

For Meta CAPI (v20.0), TikTok Events API, LinkedIn Conversions API, Microsoft Advertising, and WooCommerce support, upgrade to OmniSignal Pro.

License

The MIT License (MIT). Please see License File for more information.