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 Facebook Pixel Laravel Package

combindma/laravel-facebook-pixel

Easily integrate Facebook Pixel into your Laravel app. Track page views and custom events from PHP or Blade, fire standard events, and manage configuration with a lightweight, developer-friendly API for adding Meta Pixel tracking to any Laravel project.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and wire up

composer require <vendor>/laravel-facebook-business-sdk
php artisan vendor:publish --tag=facebook-business-config

Add credentials to .env rather than the config file:

FACEBOOK_APP_ID=
FACEBOOK_APP_SECRET=
FACEBOOK_ACCESS_TOKEN=
FACEBOOK_BUSINESS_ID=
FACEBOOK_API_VERSION=v23.0

The package is a thin Laravel-flavoured wrapper around facebook/php-business-sdk, so the mental model is: the package gives you config + container bindings + a facade; the SDK itself (FacebookAds\Api, FacebookAds\Object\...) does the actual work. Register the SDK's Api instance once (typically in a service provider or a package-provided singleton) and resolve it from the container instead of calling Api::init() in controllers.

Where to look first

  1. config/facebook-business.php — the only file you must understand up front.
  2. The package's service provider — confirms whether Api is bound as a singleton and whether a facade alias is registered.
  3. The SDK's FacebookAds\Object\AdAccount, Campaign, AdSet, Ad classes — these are what you'll use 90% of the time.

First use case — read something, don't write anything yet:

use FacebookAds\Object\AdAccount;

$account = new AdAccount('act_1234567890');
$campaigns = $account->getCampaigns([
    'fields' => ['id', 'name', 'status', 'objective', 'daily_budget'],
    'limit'  => 25,
]);

Then composer update once on a clean branch and confirm the resolved SDK version is 25.0.1 or lower (see Gotchas — 5.3.6 explicitly pins this).

Implementation Patterns

Wrap the SDK, don't sprinkle it

The SDK objects are stateful and awkward to fake. Put them behind your own service so tests and call sites stay clean:

final class MetaAdsClient
{
    public function __construct(private readonly AdAccount $account) {}

    public function activeCampaigns(): Collection
    {
        return collect($this->account->getCampaigns([
            'fields' => ['id','name','objective','daily_budget'],
            'effective_status' => ['ACTIVE'],
        ])->getArrayCopy());
    }
}

Bind AdAccount in a service provider using the configured ad account ID — then every job and controller gets the right account injected. For multi-account apps, use a factory keyed by account ID and a scoped() binding.

Pagination — always use the cursor, never limit: 500

The SDK exposes a cursor on every edge. The pattern that survives large accounts:

$cursor = $account->getCampaigns(['fields' => ['id','name'], 'limit' => 100]);

while ($cursor->valid()) {
    foreach ($cursor as $campaign) {
        // persist / dispatch
    }
    $cursor->fetchAfter(); // follows paging.next
}

Do this inside a queued job with a checkpoint (last processed ID) so a rate-limit exception doesn't restart the whole crawl.

Heavy reads belong in jobs

Sync calls will blow past PHP's max_execution_time and Laravel's request timeout. Standard pattern: controller dispatches SyncCampaignsJob, job uses $this->release($backoff) on FacebookAds\Http\Exception\RequestException with a rate-limit code. Wrap the loop in RateLimiter or Redis::throttle() so a burst of jobs doesn't hit Meta's per-app limits.

Batching for writes

When creating/updating more than a handful of objects, use the SDK's batch API rather than N sequential calls. It's the single biggest performance lever in this package — orders of magnitude fewer round trips, and partial failures come back as per-item results rather than an exception killing the whole loop.

Webhooks / lead ads

If you consume Lead Ads or Messenger webhooks, verify X-Hub-Signature-256 against the app secret before touching the payload, and return 200 fast, then process the payload in a job. Keep the verification in middleware, not the controller — you'll reuse it.

Token handling

Long-lived tokens still expire. Store them in the database (encrypted cast), not .env, if you support multiple businesses or need rotation. Add a scheduled command that exchanges/refreshes and alerts on failure — a silently expired token looks identical to "no campaigns" in your UI.

Gotchas and Tips

The 5.3.6 pin is the headline. The package now requires facebook/php-business-sdk ~25.0.0,<25.0.2. Practically:

  • If you have 25.0.2 or later locked in composer.lock, composer update will downgrade it. Check the diff before committing — a silent downgrade in a lockfile is easy to miss in review.
  • If anything else in your dependency tree requires >=25.0.2, you'll get an unresolvable conflict and Composer will refuse. That's intentional; don't try to force it with --ignore-platform-reqs or a replace block.
  • You cannot upgrade to 25.0.2+ while on this package version. Pin the package ("5.3.6") rather than floating (^5.3) so a future release doesn't move the SDK version under you unexpectedly.
  • The constraint is a hard requirement in composer.json, not a runtime check — nothing will warn you at boot time if you somehow end up on a bad version.

Debugging is opaque by default. Attach a logger to see the wire traffic:

Api::instance()->setLogger(new \Monolog\Logger('fb'));

Also inspect Api::instance()->getHttpClient()->getLastRequest() / getLastResponse() after a failure — the SDK throws generic RequestExceptions and the real error detail (error_user_msg, error_subcode) lives in the response body.

Error codes worth branching on. 17/613 = rate limit (back off, don't retry immediately), 190 = invalid/expired token (alert, don't retry), 100 = bad parameter (your bug, fail loudly), 368 = temporarily blocked. Catching RequestException and rethrowing everything is the most common mistake.

Config caching bites. php artisan config:cache is fine, but any code calling env() directly inside the package's service provider will return null in production. If the client silently uses an empty token, check this first.

Api::init() is global state. It's a static singleton in the SDK. If you ever need two businesses with different tokens in one process, you must re-init between calls — which is why per-request apps should use one instance, and multi-tenant apps should isolate by job. Don't assume the package's binding handles this for you; verify in the service provider.

Version field is your friend and your enemy. Meta deprecates API versions on a rolling schedule. If the package's default api_version in config is older than ~2 years, set it explicitly in .env and add a calendar reminder — deprecations arrive as unhelpful 400s.

Extension points. The HttpClient is swappable via Api::instance()->setHttpClient() — useful for injecting retry middleware or logging. If the package doesn't expose a configuration hook for the client, that's a reasonable place to send a PR rather than monkey-patching in a service provider.

Testing. Don't hit the real API in tests. Since the SDK classes are concrete and hard to mock, fake at your wrapper boundary (MetaAdsClient) rather than trying to mock AdAccount. For integration tests, record real responses once and replay them via a custom HttpClient.

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