PHPackages                             alexwestergaard/php-ga4 - 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. alexwestergaard/php-ga4

ActiveLibrary[API Development](/categories/api)

alexwestergaard/php-ga4
=======================

PHP Library for Google Analytics 4 with Server Side Tagging

v2.1.2(3mo ago)63144.7k↓26.5%91UnlicensePHPPHP &gt;=8.0,&lt;=8.6CI passing

Since Jul 13Pushed 2mo ago3 watchersCompare

[ Source](https://github.com/aawnu/php-ga4)[ Packagist](https://packagist.org/packages/alexwestergaard/php-ga4)[ Docs](https://github.com/aawnu/php-ga4)[ RSS](/packages/alexwestergaard-php-ga4/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (2)Versions (39)Used By (1)

Google Analytics 4 Server-Side PHP Package
==========================================

[](#google-analytics-4-server-side-php-package)

[![Version](https://camo.githubusercontent.com/71a8ac5ec30e8bc02ad0740aa5d4fc3ff8d66ff0c461eb078b5e05aa552ea30a/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f616c657877657374657267616172642f7068702d6761343f636f6c6f723d626c7565266c6162656c3d737461626c6525323072656c65617365)](https://github.com/aawnu/php-ga4/releases/latest)[![Version](https://camo.githubusercontent.com/2e7f9f2be76e33d73eea66e65b9b867df9b34983ca9bb3d1270e72f67916e0a3/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f616c657877657374657267616172642f7068702d6761343f636f6c6f723d79656c6c6f7726696e636c7564655f70726572656c6561736573266c6162656c3d6c617465737425323072656c65617365)](https://github.com/aawnu/php-ga4/releases)[![Code Coverage Badge](https://raw.githubusercontent.com/AlexWestergaard/php-ga4/image-data/coverage.svg)](https://raw.githubusercontent.com/AlexWestergaard/php-ga4/image-data/coverage.svg)[![PHPVersion](https://camo.githubusercontent.com/11778bfb484d32a6fb59f99910db65e7bfb78bf61ea70ec7071dca2a3a16c9ba/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f616c657877657374657267616172642f7068702d6761343f636f6c6f723d626c7565)](https://www.php.net/releases)[![Size](https://camo.githubusercontent.com/c47806eb6fad03633f049e5d2930aeb5aafd478a7d9421a7fa7f17f5b989696d/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c616e6775616765732f636f64652d73697a652f6161776e752f7068702d6761343f636f6c6f723d626c7565)](https://github.com/aawnu/php-ga4/releases/latest) [![Contributors](https://camo.githubusercontent.com/5650e028e592852a079d826b5aef490965abfd70ae355a848afd7d206aadb49e/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f636f6e7472696275746f72732f6161776e752f7068702d6761343f636f6c6f723d626c7565)](https://github.com/aawnu/php-ga4/graphs/contributors)[![Issues](https://camo.githubusercontent.com/1a995416b33a8c7c8ae0da57fa2b6cabb5d57c43d099618a1fbd97eae6bf9d67/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732d7261772f616c657877657374657267616172642f7068702d6761343f636f6c6f723d726564266c6162656c3d697373756573)](https://github.com/aawnu/php-ga4/issues)[![Pulls](https://camo.githubusercontent.com/c33d2f98e3826b435dfd963b9e8babee609a13600465095e91d058d1839ca12b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732d70722f6161776e752f7068702d6761343f636f6c6f723d726564266c6162656c3d70756c6c73)](https://github.com/aawnu/php-ga4/pulls)[![LastCommit](https://camo.githubusercontent.com/a32ca568c9715f9111cb68adc0fc3b9fb1cafb6820354448978b63140df69bd5/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6173742d636f6d6d69742f6161776e752f7068702d6761342f6d61737465723f636f6c6f723d726564)](https://github.com/aawnu/php-ga4/commits)

```
composer require alexwestergaard/php-ga4
```

Europe - GDPR Notice
--------------------

[](#europe---gdpr-notice)

The European Union have notified that Google Analytics does not comply with GDPR by default. This is because the frontend Client sends visitor details like their IP Address and device information with events. This can be avoided with a middle-man server inside the European Region.

- Source: Europe, GDPR, Schrems II
- Options: [Privacy controls in Google Analytics](https://support.google.com/analytics/answer/9019185?hl=en)

Getting started
---------------

[](#getting-started)

Setup requires a **Measurement ID** and **API Secret**. Go to Administrator (Bottom left) -&gt; Account -&gt; Data Streams -&gt; {Your Stream}. Here you should find Measurement ID at top and "Api Secrets for Measurement Protocol" a little down the page, where you can create yourself an `API secret`.

Go to `Administrator` (bottom left) and then select your `Account` -&gt; `Data Streams` -&gt; your stream. Here you will find `Measurement-ID` at top from and further down `Api Secrets for Measurement Protocol`, in there you can create yourself an `API Secret`.

Once you have obtained the credentials, you can initialise the Analytics like this:

```
use AlexWestergaard\PhpGa4\Analytics;

$analytics = Analytics::new(
    measurement_id: 'G-XXXXXXXX',
    api_secret: 'xYzzX_xYzzXzxyZxX',
    debug: true|false #Default: False
);
```

### Data flow

[](#data-flow)

Server Side Tagging is not supposed to replace the frontend Client and session initiation should happen through the `gtag.js` Client. The default flow is supposed to happen as follows:

1. Obtain proper GDPR Consent
2. Client/GTAG.js initiates session with Google Analytics
3. Google Analytics sends `_ga` and `_gid` cookies back to Client/GTAG.js
4. Server uses `_ga` (or `_gid`) to send/populate events
    - Eg. GenerateLead, Purchase, Refund and other backend handled events.

Note: It is entirely possible to push events to backend without acquiring the session cookies from Google Analytics; you will, however, lose information bundled inside the `gtag.js` request if you do not figure out how to push that via backend too. You can replace the `_ga` and `_gid` sessions with your own uniquely generated id.

All requests should follow this structure and contain at least 1 event for Google Analytics to accept it.

```
Analytics [
    Events [
        Event {
            Parameters
            ? Items [
                Item Parameters
            ]
        }
    ]
    User Properties [
        Properties {
            Key: Value
        }
    ]
    ? Consent {
      Key: Value
    }
    ? User Data {
      Key: Value
    }
]
```

Events
------

[](#events)

This is a list of prebuilt events as shown in the documentation. All events have the following parameters to locate trigger location of each event.

### Default

[](#default)

- [PageView](src/Event/PageView.php)
- [Share](src/Event/Share.php)
- [Signup](src/Event/Signup.php)
- [Login](src/Event/Login.php)
- [Search](src/Event/Search.php)
- [SelectContent](src/Event/SelectContent.php)
- [SelectItem](src/Event/SelectItem.php)
- [SelectPromotion](src/Event/SelectPromotion.php)
- [ViewItem](src/Event/ViewItem.php)
- [ViewItemList](src/Event/ViewItemList.php)
- [ViewPromotion](src/Event/ViewPromotion.php)
- [ViewSearchResults](src/Event/ViewSearchResults.php)

### E-commerce

[](#e-commerce)

- [GenerateLead](src/Event/GenerateLead.php)
- [AddToWishlist](src/Event/AddToWishlist.php)
- [AddToCart](src/Event/AddToCart.php)
- [ViewCart](src/Event/ViewCart.php)
- [RemoveFromCart](src/Event/RemoveFromCart.php)
- [BeginCheckout](src/Event/BeginCheckout.php)
- [AddPaymentInfo](src/Event/AddPaymentInfo.php)
- [AddShippingInfo](src/Event/AddShippingInfo.php)
- [Purchase](src/Event/Purchase.php)
- [Refund](src/Event/Refund.php)

### Engagement / Gaming

[](#engagement--gaming)

- [EarnVirtualCurrency](src/Event/EarnVirtualCurrency.php)
- [SpendVirtualCurrency](src/Event/SpendVirtualCurrency.php)
- [LevelUp](src/Event/LevelUp.php)
- [PostScore](src/Event/PostScore.php)
- [TutorialBegin](src/Event/TutorialBegin.php)
- [TutorialComplete](src/Event/TutorialComplete.php)
- [UnlockAchievement](src/Event/UnlockAchievement.php)
- [JoinGroup](src/Event/JoinGroup.php)

### Reporting

[](#reporting)

- [Exception](src/Event/Exception.php)

Frontend &amp; Backend Communication
------------------------------------

[](#frontend--backend-communication)

This library is built for backend server side tracking, but you will probably trigger most events through frontend with Javascript or Websockets. There will be 2 examples, one as pure backend for logged/queued events and one for frontend to backend communication.

### Logging / Queue

[](#logging--queue)

```
// require vendor/autoload.php

use AlexWestergaard\PhpGa4\Exception;
use AlexWestergaard\PhpGa4\Analytics;
use AlexWestergaard\PhpGa4\Event;
use AlexWestergaard\PhpGa4\Item;

// pseudo function, make your own logic here
$visitors = getVisitorsWithEvents();

foreach ($visitors as $visitor) {
    // Group of events, perhaps need logic to change from json or array to event objects
    // Maybe its formatted well for the > ConvertHelper::parseEvents([...]) < helper
    $groups = $visitor['events'];

    // If gtag.js, this can be the _ga or _gid cookie
    // This can be any kind of session identifier
    // Usually derives from $_COOKIE['_ga'] or $_COOKIE['_gid'] set by GTAG.js
    $client = $visitor['client_id'];

    // load logged in user/visitor
    // This can be any kind of unique identifier, readable is easier for you
    // Just be wary not to use GDPR sensitive information
    $user = $visitor['user_id'];
    $userParameters = $visitor["user_parameters"]

    // Render events grouped on time (max offset is 3 days from NOW)
    foreach ($groups as $time => $data) {
        try {
                $analytics = Analytics::new($measurementId, $apiSecret)
                    ->setClientId($client)
                    ->setTimestampMicros($time);

                if ($user !== null) {
                    $analytics->setUserId($user);
                }

                // pseudo logic for adding user parameters
                $analytics->addUserParameter(...$userParameters);
                // pseudo logic for adding events
                $analytics->addEvent(...$data['events']);

                // send events to Google Analytics
                $analytics->post();
        } catch (Exception\Ga4Exception $exception) {
            // Handle exception
            // Exceptions might be stacked, check: $exception->getPrevious();
            ExceptionTrail(function(Exception $e) {/*...*/}, $exception)
        }
    }
}

// pseudo function to trail the exception tree
function ExceptionTrail(callable $handler, Exception $e) {
    $handler($e);

    $prev = $e->getPrevious();
    if ($prev instanceof Exception) {
        ExceptionTrail($handler, $prev);
    }
}
```

Custom Events
-------------

[](#custom-events)

You can build your own custom events. All you need is to implement and fullfill the `AlexWestergaard\PhpGa4\Facade\Type\EventType` facade/interface. If you want quality of life features, then you can extend your event from `AlexWestergaard\PhpGa4\Helper\EventHelper` or `AlexWestergaard\PhpGa4\Helper\EventMainHelper` and overwrite as you see fit.

```
// EventHelper implements AlexWestergaard\PhpGa4\Facade\Type\EventType
class ExampleEvent extends AlexWestergaard\PhpGa4\Helper\EventHelper
{
    // variables should be nullable as unset() will set variable as null
    protected null|mixed $my_variable;
    protected null|mixed $my_required_variable;

    // Arrays should always be instanciated empty
    protected array $my_array = [];

    public function getName(): string
    {
        return 'example_event';
    }

    public function getParams(): array
    {
        return [
            'my_variable',
            'my_array',
        ];
    }

    public function getRequiredParams(): array
    {
        return [
            'my_required_variable',
        ];
    }

    public function setMyVariable(string $value)
    {
        $this->my_variable = $value;
        return $this; // Allows chained events
    }

    public function setMyRequiredVariable(string $value)
    {
        $this->my_required_variable = $value;
        return $this; // Allows chained events
    }
}
```

Debug
-----

[](#debug)

Measurement protocol for GA4 has debug functionality that can be enabled with the `debug` parameter in the Analytics constructor.

```
$analytics = Analytics::new(
    measurement_id: 'G-XXXXXXXX',
    api_secret: 'xYzzX_xYzzXzxyZxX',
    debug: true // default: false
);
```

When `Debug` is enabled then events are sent to `https://www.google-analytics.com/debug/mp/collect` where issues will be caught with [GA4Exception](https://github.com/aawnu/php-ga4/blob/master/src/Exception/Ga4Exception.php) (Be aware of `$exception->getPrevious()` stacks); such response will look as follows:

```
{
  "validationMessages": [
    {
      "fieldPath": "events",
      "description": "Event at index: [0] has invalid name [_badEventName]. Names must start with an alphabetic character.",
      "validationCode": "NAME_INVALID"
    }
  ]
}
```

Notice: This library already validates that events are properly formatted when added to analytics (`$analytics->addEvent(...)`).

Two important points:

- Events sent to the Validation Server will not show up in reports.
- There is no way for events sent through measurement protocol (Server Side) to show up in the `debugView` in Google Analytics Admin.

Documentation
-------------

[](#documentation)

- [Measurement Protocol](https://developers.google.com/analytics/devguides/collection/protocol/ga4)
- [Measurement Protocol: Reference](https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference?client_type=gtag)
- [Measurement Protocol: User Properties](https://developers.google.com/analytics/devguides/collection/protocol/ga4/user-properties?client_type=gtag)
- [Measurement Protocol: Events](https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference/events)
    - [Reserved Event Names](https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference?client_type=gtag#reserved_event_names)
- [Measurement Protocol: Validation](https://developers.google.com/analytics/devguides/collection/protocol/ga4/validating-events?client_type=gtag)
- [Measurement Protocol: User Data](https://developers.google.com/analytics/devguides/collection/ga4/uid-data)

###  Health Score

60

—

FairBetter than 99% of packages

Maintenance81

Actively maintained with recent releases

Popularity46

Moderate usage in the ecosystem

Community20

Small or concentrated contributor base

Maturity77

Established project with proven stability

 Bus Factor1

Top contributor holds 87.4% 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

Every ~36 days

Recently: every ~84 days

Total

37

Last Release

112d ago

Major Versions

v1.3.0-alpha → v2.0.02025-03-02

PHP version history (8 changes)v1.0.0PHP ^7.0 || ^8.0

v1.0.2PHP ^7.0|^8.0

v1.1.0PHP ^8.0

v1.1.2-alphaPHP ^8.0.0|8.1.0|8.2.0

v1.1.2-betaPHP &gt;=8.0,&lt;8.3

v1.1.6PHP &gt;=8.0,&lt;8.4

v1.2.4PHP &gt;=8.0,&lt;8.5

v2.1.1PHP &gt;=8.0,&lt;=8.6

### Community

Maintainers

![](https://www.gravatar.com/avatar/4903a6135aa550d39596795a8326f4c675e2bdedf923bf84c45625161b88c7c5?d=identicon)[AlexWestergaard](/maintainers/AlexWestergaard)

---

Top Contributors

[![aawnu](https://avatars.githubusercontent.com/u/2266126?v=4)](https://github.com/aawnu "aawnu (159 commits)")[![8ctopus](https://avatars.githubusercontent.com/u/13252042?v=4)](https://github.com/8ctopus "8ctopus (13 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (6 commits)")[![jordykouters](https://avatars.githubusercontent.com/u/12907728?v=4)](https://github.com/jordykouters "jordykouters (2 commits)")[![tobz-nz](https://avatars.githubusercontent.com/u/443054?v=4)](https://github.com/tobz-nz "tobz-nz (2 commits)")

---

Tags

composer-libraryga4gdprgoogle-analyticsgoogle-analytics-4phpphp-libraryphp8php80php81php82php83server-side-trackingsstphptrackinganalyticsgoogle-analyticsphp8gdprphp8.3php82server side trackingphp80ga4php81sstanalytics 4google analytics 4php84

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/alexwestergaard-php-ga4/health.svg)

```
[![Health](https://phpackages.com/badges/alexwestergaard-php-ga4/health.svg)](https://phpackages.com/packages/alexwestergaard-php-ga4)
```

###  Alternatives

[maxbeckers/amazon-alexa-php

Php library for amazon echo (alexa) skill development.

11554.0k2](/packages/maxbeckers-amazon-alexa-php)[irazasyed/laravel-gamp

Send analytics data to Google Analytics from Laravel. A package for GA Measurement Protocol API

3361.6M1](/packages/irazasyed-laravel-gamp)[marcin-orlowski/laravel-api-response-builder

Helps building nice, normalized and easy to consume Laravel REST API.

837458.6k3](/packages/marcin-orlowski-laravel-api-response-builder)[jeffreyhyer/bamboohr

PHP SDK for the BambooHR API

1077.3k1](/packages/jeffreyhyer-bamboohr)[jeffreyhyer/alpaca-trade-api-php

PHP SDK for the Alpaca trade API

285.0k](/packages/jeffreyhyer-alpaca-trade-api-php)[kuvardin/telegram-bots-api

SDK for Telegram bots API

145.5k](/packages/kuvardin-telegram-bots-api)

PHPackages © 2026

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