PHPackages                             esign/laravel-conversions-api - 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. esign/laravel-conversions-api

ActiveLibrary[API Development](/categories/api)

esign/laravel-conversions-api
=============================

A laravel wrapper package around the Facebook Conversions API

2.8.0(2mo ago)69145.4k↓10.6%14MITPHPPHP ^8.1CI passing

Since Nov 17Pushed 2mo ago6 watchersCompare

[ Source](https://github.com/esign/laravel-conversions-api)[ Packagist](https://packagist.org/packages/esign/laravel-conversions-api)[ Docs](https://github.com/esign/laravel-conversions-api)[ RSS](/packages/esign-laravel-conversions-api/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (12)Versions (18)Used By (0)

Interact with the Facebook Conversions API
==========================================

[](#interact-with-the-facebook-conversions-api)

[![Latest Version on Packagist](https://camo.githubusercontent.com/8c685aff8c7b804c92ec9232c433a22057603a80a259581f9941b676f0f03ff2/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f657369676e2f6c61726176656c2d636f6e76657273696f6e732d6170692e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/esign/laravel-conversions-api)[![Total Downloads](https://camo.githubusercontent.com/3453a4f6aa30137e8048f4749bdc10461de5275c1773aa00596d501f385d28d1/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f657369676e2f6c61726176656c2d636f6e76657273696f6e732d6170692e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/esign/laravel-conversions-api)[![GitHub Actions](https://github.com/esign/laravel-conversions-api/actions/workflows/main.yml/badge.svg)](https://github.com/esign/laravel-conversions-api/actions/workflows/main.yml/badge.svg)

This package allow you to easily interact with the [Facebook Conversions API](https://developers.facebook.com/docs/marketing-api/conversions-api/).

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

[](#installation)

You can install the package via composer:

```
composer require esign/laravel-conversions-api
```

Next up, you can publish the configuration file:

```
php artisan vendor:publish --provider="Esign\ConversionsApi\ConversionsApiServiceProvider" --tag="config"
```

The config file will be published as config/conversions-api.php with the following content:

```
return [
    /**
     * The access token used by the Conversions API.
     */
    'access_token' => env('CONVERSIONS_API_ACCESS_TOKEN'),

    /**
     * The pixel ID used by the Conversions API.
     */
    'pixel_id' => env('CONVERSIONS_API_PIXEL_ID'),

    /**
     * The Google Tag Manager container ID used in case you're deduplicating
     * events through Google Tag Manager instead of Facebook Pixel directly.
     * Should look something like "GTM-XXXXXX".
     */
    'gtm_id' => env('GOOGLE_TAG_MANAGER_ID'),

    /**
     * The Conversions API comes with a nice way to test your events.
     * You may use this config variable to set your test code.
     */
    'test_code' => env('CONVERSIONS_API_TEST_CODE'),
];
```

In case you want to customize the view components you may also publish the views:

```
php artisan vendor:publish --provider="Esign\ConversionsApi\ConversionsApiServiceProvider" --tag="views"
```

Conversions API
---------------

[](#conversions-api)

### Events

[](#events)

To add events to the conversions API you may use the `addEvent`, `addEvents` or `setEvents` methods. Retrieving or clearing events may be done using the `getEvents` and `clearEvents` methods:

```
use Esign\ConversionsApi\Facades\ConversionsApi;
use FacebookAds\Object\ServerSide\UserData;
use FacebookAds\Object\ServerSide\Event;

ConversionsApi::addEvent(
    (new Event())->setEventName('PageView')->setEventId('abc')
);

ConversionsApi::setEvents([
    (new Event())->setEventName('PageView')->setEventId('abc'),
    (new Event())->setEventName('Purchase')->setEventId('xyz'),
]);

ConversionsApi::getEvents();
ConversionsApi::clearEvents();
```

Adding events won't cause them to be sent to the Conversions API. To actually send the events you must call the `sendEvents` method:

```
use Esign\ConversionsApi\Facades\ConversionsApi;

ConversionsApi::sendEvents();
```

#### Creating event classes

[](#creating-event-classes)

To make things a bit cleaner you may extend Facebook's default event class:

```
use Esign\ConversionsApi\Facades\ConversionsApi;
use FacebookAds\Object\ServerSide\ActionSource;
use FacebookAds\Object\ServerSide\Event;

class PurchaseEvent extends Event
{
    public static function create(): static
    {
        return (new static())
            ->setActionSource(ActionSource::WEBSITE)
            ->setEventName('Purchase')
            ->setEventTime(time())
            ->setEventSourceUrl(request()->fullUrl())
            ->setEventId((string) Str::uuid())
            ->setUserData(ConversionsApi::getUserData());
    }
}
```

```
ConversionsApi::addEvent(
    PurchaseEvent::create()
);
```

### User Data

[](#user-data)

This package also comes with a way to define default user data for the user of the current request. You may do so by calling the `setUserData` method. You can set the user data for every incoming request by creating a custom middleware like this one:

```
namespace App\Http\Middleware;

use Esign\ConversionsApi\Facades\ConversionsApi;
use Esign\ConversionsApi\Objects\DefaultUserData;

class InitializeFacebookUserData
{
    public function handle(Request $request, Closure $next): Response
    {
        ConversionsApi::setUserData(
            DefaultUserData::create()
                ->setEmail($request->user()?->email)
        );

        return $next($request);
    }
}
```

You can now use it in `App\Http\Kernel` as a global middleware or a route middleware.

You may now pass the user data along with your events:

```
use Esign\ConversionsApi\Facades\ConversionsApi;
use FacebookAds\Object\ServerSide\Event;

ConversionsApi::addEvent(
    (new Event())->setUserData(ConversionsApi::getUserData())
);
```

Event deduplication
-------------------

[](#event-deduplication)

This package comes with a few ways to assist you in [deduplicating browser and server events](https://developers.facebook.com/docs/marketing-api/conversions-api/deduplicate-pixel-and-server-events/). This can either be done using the Facebook Pixel directly or through Google Tag Manager's data layer.

### Facebook Pixel

[](#facebook-pixel)

Before attempting to send events through Facebook Pixel make sure to load the pixel script:

```

```

This will render the following html:

```

    !function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
    n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
    n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
    t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
    document,'script','https://connect.facebook.net/en_US/fbevents.js');

    fbq('init', 'your-configured-pixel-id', {});

```

This package will attempt to provide as much advanced matching data as possible by using user data from the `ConversionsApi`. For example when an email address is set, it will automatically be provided to the init method:

```
ConversionsApi::setUserData(
    (new UserData())->setEmail('john@example.com')
);
```

```
fbq('init', 'your-configured-pixel-id', {"em": "john@example.com"});
```

Now that your Pixel is correctly initialized, it's time to send some events. Sadly the parameters between the Conversions API and Facebook Pixel are not identical, so they must be mapped to the [correct format](https://developers.facebook.com/docs/meta-pixel/reference). An easy way of doing this is by extending the `FacebookAds\Object\ServerSide\Event` class and implementing the `Esign\ConversionsApi\Contracts\MapsToFacebookPixel` interface on it:

```
use Esign\ConversionsApi\Contracts\MapsToFacebookPixel;
use Esign\ConversionsApi\Facades\ConversionsApi;
use FacebookAds\Object\ServerSide\ActionSource;
use FacebookAds\Object\ServerSide\Event;

class PurchaseEvent extends Event implements MapsToFacebookPixel
{
    public static function create(): static
    {
        return (new static())
            ->setActionSource(ActionSource::WEBSITE)
            ->setEventName('Purchase')
            ->setEventTime(time())
            ->setEventSourceUrl(request()->fullUrl())
            ->setEventId((string) Str::uuid())
            ->setUserData(ConversionsApi::getUserData());
    }

    public function getFacebookPixelEventType(): string
    {
        return 'track';
    }

    public function getFacebookPixelEventName(): string
    {
        return $this->getEventName();
    }

    public function getFacebookPixelCustomData(): array
    {
        $customData = $this->getCustomData();

        return array_filter([
            'currency' => $customData?->getCurrency(),
            'value' => $customData?->getValue(),
        ]);
    }

    public function getFacebookPixelEventData(): array
    {
        return array_filter(['eventID' => $this->getEventId()]);
    }
}
```

You may now pass any class that implements the `MapsToFacebookPixel` interface to the view component responsible for tracking Facebook Pixel events:

```
use FacebookAds\Object\ServerSide\CustomData;
use Illuminate\Support\Str;

$event = PurchaseEvent::create()->setCustomData(
    (new CustomData())->setCurrency('EUR')->setValue(10)
);
```

```

```

This will render the following script tag:

```

    fbq('track', 'Purchase', {"currency": "EUR", "value": 10}, {"eventID": "ccf928e1-56fd-4376-bee3-dda0d7dbe136"});

```

To retrieve a list of all events that implement the `MapsToFacebookPixel` interface you may call the `filterFacebookPixelEvents` method:

```
@foreach(ConversionsApi::getEvents()->filterFacebookPixelEvents() as $event)

@endforeach
```

In case you want more control over what's being rendered, you may always use the anonymous component:

```

```

### Google Tag Manager

[](#google-tag-manager)

Before attempting to deduplicate events through GTM make sure to configure your GTM container id and include the necessary scripts:

```
GOOGLE_TAG_MANAGER_ID=GTM-XXXXXX
```

```

    {{-- ... --}}

    {{-- ... --}}

```

This package comes with a view component that will map all user data from the `ConversionsApi` to dataLayer variables:

```

```

For example when an email address is set, it will be automatically mapped to a dataLayer variable. Check the [source](src/View/Components/DataLayerUserDataVariable.php) of the view component to see a list of all possible variables.

```
ConversionsApi::setUserData(
    (new UserData())->setEmail('john@example.com')
);
```

```
window.dataLayer.push({"conversionsApiUserEmail": "john@example.com"});
```

Now that your Pixel through GTM is correctly initialized, it's time to send some events. An easy way of doing this is by extending the `FacebookAds\Object\ServerSide\Event` class and implementing the `Esign\ConversionsApi\Contracts\MapsToDataLayer` interface on it:

```
use Esign\ConversionsApi\Contracts\MapsToDataLayer;
use Esign\ConversionsApi\Facades\ConversionsApi;
use FacebookAds\Object\ServerSide\ActionSource;
use FacebookAds\Object\ServerSide\Event;

class PurchaseEvent extends Event implements MapsToDataLayer
{
    public static function create(): static
    {
        return (new static())
            ->setActionSource(ActionSource::WEBSITE)
            ->setEventName('Purchase')
            ->setEventTime(time())
            ->setEventSourceUrl(request()->fullUrl())
            ->setEventId((string) Str::uuid())
            ->setUserData(ConversionsApi::getUserData());
    }

    public function getDataLayerArguments(): array
    {
        $customData = $this->getCustomData();

        return [
            'event' => 'conversionsApiPurchase',
            'conversionsApiPurchaseEventId' => $this->getEventId(),
            'conversionsApiPurchaseCurrency' => $customData?->getCurrency(),
            'conversionsApiPurchaseValue' => $customData?->getValue(),
        ];
    }
}
```

You may now pass any class that implements the `MapsToDataLayer` interface to the view component responsible for tracking Facebook Pixel events:

```
use FacebookAds\Object\ServerSide\CustomData;
use Illuminate\Support\Str;

$event = PurchaseEvent::create()->setCustomData(
    (new CustomData())->setCurrency('EUR')->setValue(10)
);
```

```

```

This will render the following script tag:

```

    window.dataLayer.push({
        "event": "conversionsApiPurchase",
        "conversionsApiPurchaseEventId": "e2481afc-5af4-4483-bc4b-33f08e195e3a",
        "conversionsApiPurchaseCurrency": "EUR",
        "conversionsApiPurchaseValue": 120
    });

```

To retrieve a list of all events that implement the `MapsToDataLayer` interface you may call the `filterDataLayerEvents` method:

```
@foreach(ConversionsApi::getEvents()->filterDataLayerEvents() as $event)

@endforeach
```

In case you want more control over what's being rendered, you may always use the anonymous component:

```

```

PageView Events
---------------

[](#pageview-events)

This package ships with some helpers to track `PageView` events out of the box. These helpers will automatically send both Conversions API &amp; Facebook Pixel events and provide event deduplication.

> **Note**Make sure to always include these view components after you've already looped over any other events currently defined on the ConversionsApi. Including these view components will clear any existing events.

In case you're using the Facebook Pixel directly:

```

```

Or by using Google Tag Manager. The data-layer variable to deduplicate events is called `conversionsApiPageViewEventId`.

```

```

Troubleshooting
---------------

[](#troubleshooting)

### PageView events are not shown as deduplicated in the test events dashboard

[](#pageview-events-are-not-shown-as-deduplicated-in-the-test-events-dashboard)

Event deduplication for PageView events should be fine out of the box, since the event name and event id parameters have been provided. However, when serving your application locally the ip address returned by Laravel's `request()->ip()` will be `127.0.0.1`. This is different from the ip address sent through Facebook Pixel, causing the Conversions API and Facebook Pixel events to not be deduplicated. This issue should solve itself once the application will be ran in production.

### Whitelisting Cookies in Laravel

[](#whitelisting-cookies-in-laravel)

When using `\App\Http\Middleware\EncryptCookies::class` in `\App\Http\Kernel::class`, ensure to whitelist \_fbp and \_fbc cookies to prevent null values in loading `DefaultUserData::create()`. Update the $except property in the EncryptCookies middleware as shown below:

```
