PHPackages                             electrictomcat/laravel-google-ads-conversions - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. electrictomcat/laravel-google-ads-conversions

ActiveLibrary[API Development](/categories/api)

electrictomcat/laravel-google-ads-conversions
=============================================

Drop-in offline conversion tracking for Laravel apps using Google Ads.

v0.1.0(1mo ago)028[2 PRs](https://github.com/electrictomcat/laravel-google-ads-conversions/pulls)MITPHPPHP ^8.3CI passing

Since May 3Pushed 3w agoCompare

[ Source](https://github.com/electrictomcat/laravel-google-ads-conversions)[ Packagist](https://packagist.org/packages/electrictomcat/laravel-google-ads-conversions)[ Docs](https://github.com/electrictomcat/laravel-google-ads-conversions)[ GitHub Sponsors](https://github.com/electrictomcat)[ RSS](/packages/electrictomcat-laravel-google-ads-conversions/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (1)Dependencies (13)Versions (5)Used By (0)

Laravel Google Ads Conversions
==============================

[](#laravel-google-ads-conversions)

[![Latest Version on Packagist](https://camo.githubusercontent.com/5a97f5c5be8acf46fe46b943ed64648aab634c917e550e48286d17c728ce82b9/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f656c656374726963746f6d6361742f6c61726176656c2d676f6f676c652d6164732d636f6e76657273696f6e732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/electrictomcat/laravel-google-ads-conversions)[![GitHub Tests Action Status](https://camo.githubusercontent.com/562052548fe7077bdbcf9b6ca218b5b17638b64db206ff77cdd72c046330640a/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f656c656374726963746f6d6361742f6c61726176656c2d676f6f676c652d6164732d636f6e76657273696f6e732f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/electrictomcat/laravel-google-ads-conversions/actions?query=workflow%3Arun-tests+branch%3Amain)[![GitHub Code Style Action Status](https://camo.githubusercontent.com/e2ab2bc0bf87f28644daaceaf9b0482ca63051e234269b22d294f134af588736/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f656c656374726963746f6d6361742f6c61726176656c2d676f6f676c652d6164732d636f6e76657273696f6e732f6669782d7068702d636f64652d7374796c652d6973737565732e796d6c3f6272616e63683d6d61696e266c6162656c3d636f64652532307374796c65267374796c653d666c61742d737175617265)](https://github.com/electrictomcat/laravel-google-ads-conversions/actions?query=workflow%3A%22Fix+PHP+code+style+issues%22+branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/cc27d23da406320a6bfe5b3611727076ed1b1ed5f55b7e8360fbf8e8c4b6e981/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f656c656374726963746f6d6361742f6c61726176656c2d676f6f676c652d6164732d636f6e76657273696f6e732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/electrictomcat/laravel-google-ads-conversions)

Drop-in offline conversion tracking for Laravel apps using Google Ads.

- Captures `gclid` (and `gbraid`/`wbraid`) from incoming traffic and persists it across the visitor's session
- Records conversion events with a one-line API
- Buffers in cache, syncs to your database, and uploads to Google Ads in batched, queued jobs
- Honors Google Ads' minimum reporting delay (default 6 hours)
- Bring-your-own model — implement a small contract or use the included `Lead` model out of the box
- Supports both call-site values (`record('Event', 100)`) and config-mapped defaults

> **Status: pre-release.** Not yet on Packagist.

Installation
------------

[](#installation)

```
composer require electrictomcat/laravel-google-ads-conversions
```

Publish the config and the migration:

```
php artisan vendor:publish --tag="laravel-google-ads-conversions-config"
php artisan vendor:publish --tag="laravel-google-ads-conversions-migrations"
php artisan migrate
```

Add these to your `.env` (see [Google's OAuth setup](https://developers.google.com/google-ads/api/docs/oauth/cloud-project) for how to mint the refresh token):

```
GOOGLE_ADS_DEVELOPER_TOKEN=
GOOGLE_ADS_CLIENT_ID=
GOOGLE_ADS_CLIENT_SECRET=
GOOGLE_ADS_REFRESH_TOKEN=
GOOGLE_ADS_CUSTOMER_ID=123-456-7890
```

Register the middleware in `bootstrap/app.php`:

```
->withMiddleware(function (Middleware $middleware) {
    $middleware->web(append: [
        \ElectricTomCat\GoogleAdsConversions\Http\Middleware\CaptureGclid::class,
    ]);
})
```

Schedule the upload job in `routes/console.php`:

```
use ElectricTomCat\GoogleAdsConversions\Jobs\UploadPendingConversions;
use Illuminate\Support\Facades\Schedule;

Schedule::job(new UploadPendingConversions)->hourly();
```

Usage
-----

[](#usage)

### Recording a conversion

[](#recording-a-conversion)

From anywhere in your app — controllers, jobs, Livewire components, observers:

```
use ElectricTomCat\GoogleAdsConversions\Facades\GoogleAdsConversions;

GoogleAdsConversions::record('Quote Form', 100);
```

The first argument is your internal event name. The second is an optional value. The full signature is:

```
GoogleAdsConversions::record(
    eventName: 'Quote Form',
    value: 100.0,        // optional — falls back to per-event config
    currency: 'USD',     // optional — falls back to per-event then package default
    gclid: null,         // optional — manually override the GCLID lookup
);
```

### Mapping events to Google Ads conversion actions

[](#mapping-events-to-google-ads-conversion-actions)

Edit `config/google-ads-conversions.php`. Each event entry is either a **string** (just the action name) or an **array** with optional value/currency defaults:

```
'events' => [

    // Simple: event name → Google Ads action name (or full resource path)
    'Quote Form' => 'Quote Submission',
    'Phone Call' => 'customers/1234567890/conversionActions/111111',

    // With per-event default value/currency that the call site can still override
    'Demo Booked' => [
        'action'   => 'Demo Booked',
        'value'    => 250.00,
        'currency' => 'USD',
    ],

    // Catches any event named "Page Navigation: /anything" by prefix
    'Page Navigation' => 'Page Navigation',

],
```

The call site always wins — `record('Demo Booked', 999)` overrides the config's `250.00`. Omit the value at the call site to use the config default.

### Bring your own model

[](#bring-your-own-model)

The package ships a `Lead` model and matching migration that work out of the box. If you'd rather use your own model — say, you already have a `Visitor` table and want to track conversions there — implement the `HasConversions` contract.

The fastest path: drop the `HasConversionsTrait` onto your existing model:

```
use ElectricTomCat\GoogleAdsConversions\Contracts\HasConversions;
use ElectricTomCat\GoogleAdsConversions\Models\Concerns\HasConversionsTrait;
use Illuminate\Database\Eloquent\Casts\AsCollection;

class Visitor extends Model implements HasConversions
{
    use HasConversionsTrait;

    protected $fillable = ['gclid', 'visitor_id', 'conversions', /* ... */];

    protected $casts = [
        'conversions' => AsCollection::class,
    ];
}
```

Make sure your table has at minimum these columns:

- `gclid` (string, unique, indexed)
- `visitor_id` (uuid, nullable)
- `conversions` (json, nullable)

Then point the package at it:

```
// config/google-ads-conversions.php
'model' => \App\Models\Visitor::class,
```

For full control, implement `HasConversions` from scratch — see `src/Contracts/HasConversions.php` for the contract.

How the pipeline works
----------------------

[](#how-the-pipeline-works)

1. **Middleware** (`CaptureGclid`) — runs on the landing request, extracts `gclid` from the URL, sets cookies + session, buffers a stub lead record in cache.
2. **Recording** (`GoogleAdsConversions::record()`) — pushes a conversion entry into a per-gclid cache bucket. Cheap. Fire from anywhere, including HTTP requests where the user has no `gclid` on the URL but does have one in their session/cookie.
3. **Sync** (`syncToDatabase()`) — flushes the cache buffer into the configured model's table. Runs as the first half of the queued job.
4. **Upload** (`uploadPendingConversions()`) — finds every pending conversion older than the delay window and ships eligible batches to Google Ads via `UploadClickConversions`. Marks each shipped conversion as `'uploaded'` with a timestamp.

Testing
-------

[](#testing)

```
composer test
```

The suite uses Pest 4 + Orchestra Testbench against an in-memory SQLite database.

Changelog
---------

[](#changelog)

See [CHANGELOG.md](CHANGELOG.md).

Contributing
------------

[](#contributing)

Issues and pull requests welcome.

Credits
-------

[](#credits)

- [Tom Michael](https://github.com/electrictomcat)
- Built on top of the [Spatie package skeleton](https://github.com/spatie/package-skeleton-laravel) and [`googleads/google-ads-php`](https://github.com/googleads/google-ads-php)

License
-------

[](#license)

The MIT License (MIT). See [LICENSE.md](LICENSE.md).

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance94

Actively maintained with recent releases

Popularity10

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity41

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

37d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/ea58b0ae7e4610fca85c3684919ec085a668af6b660515561b3ed71d011c103e?d=identicon)[electrictomcat](/maintainers/electrictomcat)

---

Top Contributors

[![electrictomcat](https://avatars.githubusercontent.com/u/16545651?v=4)](https://github.com/electrictomcat "electrictomcat (6 commits)")

---

Tags

laravelelectrictomcatlaravel-google-ads-conversions

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/electrictomcat-laravel-google-ads-conversions/health.svg)

```
[![Health](https://phpackages.com/badges/electrictomcat-laravel-google-ads-conversions/health.svg)](https://phpackages.com/packages/electrictomcat-laravel-google-ads-conversions)
```

###  Alternatives

[dedoc/scramble

Automatic generation of API documentation for Laravel applications.

2.1k9.9M87](/packages/dedoc-scramble)[spatie/laravel-pdf

Create PDFs in Laravel apps

1.0k4.3M41](/packages/spatie-laravel-pdf)[defstudio/telegraph

A laravel facade to interact with Telegram Bots

815320.5k3](/packages/defstudio-telegraph)[rawilk/profile-filament-plugin

Profile &amp; MFA starter kit for filament.

3913.7k](/packages/rawilk-profile-filament-plugin)[simplestats-io/laravel-client

Analytics for Laravel. Track visitors, registrations, and payments. Discover which channels actually drive revenue, not just traffic. Server-side, GDPR compliant, ad-blocker proof.

5019.3k](/packages/simplestats-io-laravel-client)[spatie/laravel-github-webhooks

Handle GitHub webhooks in a Laravel application

93157.3k5](/packages/spatie-laravel-github-webhooks)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
