PHPackages                             lartisan/laravel-facebook-data-deletion - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. lartisan/laravel-facebook-data-deletion

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

lartisan/laravel-facebook-data-deletion
=======================================

A reusable Laravel package for handling Meta/Facebook user data deletion callbacks.

1.1.0(2mo ago)210↓90%MITPHPPHP ^8.2CI passing

Since Mar 26Pushed 2mo agoCompare

[ Source](https://github.com/lartisan/laravel-facebook-data-deletion)[ Packagist](https://packagist.org/packages/lartisan/laravel-facebook-data-deletion)[ RSS](/packages/lartisan-laravel-facebook-data-deletion/feed)WikiDiscussions main Synced 3w ago

READMEChangelog (4)Dependencies (20)Versions (5)Used By (0)

Laravel Facebook Data Deletion
==============================

[](#laravel-facebook-data-deletion)

[![Downloads](https://camo.githubusercontent.com/fda94d2fa5fb989afce3bf6c77c6235eabb54f18635b22b5edba001002038508/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6c6172746973616e2f6c61726176656c2d66616365626f6f6b2d646174612d64656c6574696f6e2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/lartisan/laravel-facebook-data-deletion/stats)[![Tests](https://camo.githubusercontent.com/ff5abbf6f63cb0598dbd7592e316fe7daf65a194059c18b52380a1bac823502a/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6c6172746973616e2f6c61726176656c2d66616365626f6f6b2d646174612d64656c6574696f6e2f66616365626f6f6b2d646174612d64656c6574696f6e2d7061636b6167652d74657374732e796d6c3f6272616e63683d6d61696e267374796c653d666c61742d737175617265266c6162656c3d7465737473)](https://github.com/lartisan/laravel-facebook-data-deletion/actions)[![Latest Version on Packagist](https://camo.githubusercontent.com/b963c4b989e31033b980f61722d8cc04c5a871b7523b7b2149bfc8fc136c1576/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6c6172746973616e2f6c61726176656c2d66616365626f6f6b2d646174612d64656c6574696f6e2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/lartisan/laravel-facebook-data-deletion)[![License](https://camo.githubusercontent.com/827589e0e475e6432c548c414600f42909e3faed79a3b2ae53f4f72ca2f21b42/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6c6172746973616e2f6c61726176656c2d66616365626f6f6b2d646174612d64656c6574696f6e2e7376673f7374796c653d666c61742d737175617265)](https://github.com/lartisan/laravel-facebook-data-deletion/blob/main/LICENSE)

A Laravel package that automates Meta / Facebook **Data Deletion Request** callbacks through a secure webhook.

It validates and decodes the incoming `signed_request`, stores a deletion tracking record, dispatches the deletion workflow asynchronously, and exposes a public status page or JSON status endpoint for the confirmation code returned to Meta.

> The package is intentionally generic. It does not assume a specific `User` model, a fixed Facebook ID column, or a hardcoded deletion strategy. Those details are provided by your application through resolver and deletion handler classes.

Table of Contents
-----------------

[](#table-of-contents)

- [Requirements](#requirements)
- [Installation](#installation)
- [Configuration](#configuration)
- [Usage](#usage)
- [Webhook Setup in Meta Dashboard](#webhook-setup-in-meta-dashboard)
- [The Status Page](#the-status-page)
- [Testing](#testing)
- [Postman / Insomnia Guide](#postman--insomnia-guide)
- [Security](#security)
- [Package Architecture](#package-architecture)

Requirements
------------

[](#requirements)

- PHP 8.2+
- Laravel 11+

The package is designed to work with Laravel 11 and Laravel 12.

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

[](#installation)

### 1. Install the package

[](#1-install-the-package)

```
composer require lartisan/laravel-facebook-data-deletion
```

### 2. Publish the configuration file

[](#2-publish-the-configuration-file)

```
php artisan vendor:publish --tag=facebook-data-deletion-config
```

### 3. Run the migration

[](#3-run-the-migration)

The package stores deletion tracking records in the `facebook_data_deletion_requests` table.

```
php artisan migrate
```

### 4. Optionally publish the status page view

[](#4-optionally-publish-the-status-page-view)

```
php artisan vendor:publish --tag=facebook-data-deletion-views
```

Configuration
-------------

[](#configuration)

The package ships with `config/facebook-data-deletion.php`.

### Environment variables

[](#environment-variables)

Add your Meta app secret to `.env`:

```
FACEBOOK_APP_SECRET=your_meta_app_secret
```

You may also optionally configure a dedicated queue connection or queue name:

```
FACEBOOK_DATA_DELETION_QUEUE_CONNECTION=redis
FACEBOOK_DATA_DELETION_QUEUE=facebook-data-deletion
```

### Default configuration

[](#default-configuration)

After publishing the config, open `config/facebook-data-deletion.php` and point `resolver` and `deletion_handler` to the two classes you will create in the next steps:

```
return [
    'app_secret' => env('FACEBOOK_APP_SECRET', env('FACEBOOK_SECRET')),

    'model' => Lartisan\FacebookDataDeletion\Models\FacebookDataDeletionRequest::class,

    // 👇 Replace with your own resolver class (see "Configuring the User model" below)
    'resolver' => App\Facebook\FacebookDeletionSubjectResolver::class,

    // 👇 Replace with your own deletion handler class (see "Configuring the deletion strategy" below)
    'deletion_handler' => App\Facebook\DeleteFacebookSubjectData::class,

    'queue' => [
        'connection' => env('FACEBOOK_DATA_DELETION_QUEUE_CONNECTION'),
        'name' => env('FACEBOOK_DATA_DELETION_QUEUE'),
    ],

    'route' => [
        'enabled' => true,
        'prefix' => 'api/facebook',
        'name_prefix' => 'facebook-data-deletion',
        'middleware' => ['api'],
        'callback_path' => 'data-deletion',
        'status_path' => 'data-deletion/{confirmationCode}',
    ],

    'view' => 'facebook-data-deletion::status',
];
```

> **How the config wires everything together**
>
> The package reads these two class names at runtime and binds them to their contracts via Laravel's service container. You never call these classes directly — they are automatically injected by the framework:
>
> - `resolver` → injected into the package's controller to look up the subject model from the Meta App-Scoped ID.
> - `deletion_handler` → injected into the `ProcessFacebookDataDeletionRequest` job to carry out the actual deletion or anonymization.
>
> All you need to do is create the two classes described below and set their fully-qualified class names in this config file.

### Configuring the User model and Facebook ID field

[](#configuring-the-user-model-and-facebook-id-field)

The package does not hardcode a user model or a `facebook_id` column. Instead, you configure a resolver class that knows how to map the Meta App-Scoped ID to the model you want to delete or anonymize.

#### Step 1 — Create the resolver class

[](#step-1--create-the-resolver-class)

#### Example: direct `facebook_id` column on `users`

[](#example-direct-facebook_id-column-on-users)

```
namespace App\Facebook;

use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Lartisan\FacebookDataDeletion\Contracts\ResolvesFacebookDeletionSubject;

class FacebookDeletionSubjectResolver implements ResolvesFacebookDeletionSubject
{
    public function resolve(string $facebookUserId): ?Model
    {
        return User::query()
            ->where('facebook_id', $facebookUserId)
            ->first();
    }
}
```

#### Example: `social_users.provider` + `social_users.provider_id`

[](#example-social_usersprovider--social_usersprovider_id)

```
namespace App\Facebook;

use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Lartisan\FacebookDataDeletion\Contracts\ResolvesFacebookDeletionSubject;

class FacebookDeletionSubjectResolver implements ResolvesFacebookDeletionSubject
{
    public function resolve(string $facebookUserId): ?Model
    {
        return User::query()
            ->whereHas('socialUsers', function ($query) use ($facebookUserId) {
                $query
                    ->where('provider', 'facebook')
                    ->where('provider_id', $facebookUserId);
            })
            ->first();
    }
}
```

#### Step 2 — Register it in the config

[](#step-2--register-it-in-the-config)

```
// config/facebook-data-deletion.php
'resolver' => App\Facebook\FacebookDeletionSubjectResolver::class,
```

### Configuring the deletion strategy

[](#configuring-the-deletion-strategy)

Your application controls how data is deleted or anonymized by implementing the deletion handler contract.

#### Step 1 — Create the deletion handler class

[](#step-1--create-the-deletion-handler-class)

```
namespace App\Facebook;

use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use Lartisan\FacebookDataDeletion\Contracts\DeletesFacebookDeletionSubjectData;
use Lartisan\FacebookDataDeletion\Models\FacebookDataDeletionRequest;

class DeleteFacebookSubjectData implements DeletesFacebookDeletionSubjectData
{
    public function delete(FacebookDataDeletionRequest $request, ?Model $subject): void
    {
        if (! $subject instanceof User) {
            return;
        }

        DB::transaction(function () use ($subject) {
            $subject->socialUsers()->delete();

            $subject->forceFill([
                'email' => 'deleted-'.now()->timestamp.'-'.$subject->email,
            ])->save();

            $subject->delete();
        });
    }
}
```

#### Step 2 — Register it in the config

[](#step-2--register-it-in-the-config-1)

```
// config/facebook-data-deletion.php
'deletion_handler' => App\Facebook\DeleteFacebookSubjectData::class,
```

Usage
-----

[](#usage)

Once installed, the package registers the callback route by default at:

```
POST /api/facebook/data-deletion

```

and the public status route at:

```
GET /api/facebook/data-deletion/{confirmationCode}

```

If you prefer a different route structure, update the `route` section in `config/facebook-data-deletion.php`.

### What Meta sends

[](#what-meta-sends)

Meta submits a POST request containing a `signed_request` field.

The package:

- validates the signature
- decodes the payload
- extracts `user_id`
- resolves the target subject through your resolver
- creates a deletion tracking record
- dispatches an async deletion job
- returns the required JSON response:

```
{
  "url": "https://your-app.test/api/facebook/data-deletion/ABCDEFG123456789ABCDEFG123456789",
  "confirmation_code": "ABCDEFG123456789ABCDEFG123456789"
}
```

Webhook Setup in Meta Dashboard
-------------------------------

[](#webhook-setup-in-meta-dashboard)

In the Meta App Dashboard, configure the **Data Deletion Callback URL** to point to your package route.

### Step-by-step

[](#step-by-step)

1. Open your Meta app.
2. Go to **App Dashboard**.
3. Open the **Data Deletion Request** or **Data Deletion Callback** section.
4. Set the callback URL to your public HTTPS endpoint.
5. Save the changes.

### Example callback URL

[](#example-callback-url)

```
https://your-domain.com/api/facebook/data-deletion

```

### Local testing with a tunnel

[](#local-testing-with-a-tunnel)

Meta cannot call a local `.test` domain directly. For local integration testing, expose your app through a public tunnel such as `ngrok` or `cloudflared`.

Example:

```
https://your-ngrok-subdomain.ngrok-free.app/api/facebook/data-deletion

```

The Status Page
---------------

[](#the-status-page)

The URL returned to Meta includes a confirmation code and points to the status route.

Example:

```
https://your-domain.com/api/facebook/data-deletion/ABCDEFG123456789ABCDEFG123456789

```

By default:

- browser requests render an HTML confirmation page
- requests with `Accept: application/json` receive structured JSON

Example JSON status response:

```
{
  "confirmation_code": "ABCDEFG123456789ABCDEFG123456789",
  "status": "completed",
  "user_found": true,
  "requested_at": "2026-03-26T15:00:00+00:00",
  "completed_at": "2026-03-26T15:00:01+00:00"
}
```

Testing
-------

[](#testing)

### Generate a valid `signed_request` in Tinker / Tinkerwell

[](#generate-a-valid-signed_request-in-tinker--tinkerwell)

Use the following PHP snippet to generate a Meta-compatible `signed_request` for Postman, Insomnia, or cURL testing:

```
$payload = [
    'algorithm' => 'HMAC-SHA256',
    'issued_at' => time(),
    'user_id' => 'app-scoped-id-123',
];

$appSecret = config('facebook-data-deletion.app_secret');

if (! is_string($appSecret) || $appSecret === '') {
    throw new RuntimeException('facebook-data-deletion.app_secret is not configured.');
}

$encodedPayload = rtrim(
    strtr(base64_encode(json_encode($payload, JSON_THROW_ON_ERROR)), '+/', '-_'),
    '='
);

$signature = hash_hmac('sha256', $encodedPayload, $appSecret, true);

$encodedSignature = rtrim(
    strtr(base64_encode($signature), '+/', '-_'),
    '='
);

$signedRequest = $encodedSignature.'.'.$encodedPayload;

[
    'payload' => $payload,
    'signed_request' => $signedRequest,
];
```

### Test with cURL

[](#test-with-curl)

```
curl -X POST "https://your-app.test/api/facebook/data-deletion" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"signed_request":"PASTE_SIGNED_REQUEST_HERE"}'
```

### Run the package test suite

[](#run-the-package-test-suite)

From the package directory:

```
composer install
composer test
```

Postman / Insomnia Guide
------------------------

[](#postman--insomnia-guide)

### 1. Create a POST request

[](#1-create-a-post-request)

Use:

```
https://your-domain.com/api/facebook/data-deletion

```

### 2. Set headers

[](#2-set-headers)

```
Accept: application/json
Content-Type: application/json

```

### 3. Set the JSON body

[](#3-set-the-json-body)

```
{
  "signed_request": "PASTE_SIGNED_REQUEST_HERE"
}
```

### 4. Expected response

[](#4-expected-response)

```
{
  "url": "https://your-domain.com/api/facebook/data-deletion/ABCDEFG123456789ABCDEFG123456789",
  "confirmation_code": "ABCDEFG123456789ABCDEFG123456789"
}
```

### 5. Check the status endpoint

[](#5-check-the-status-endpoint)

Use the returned `url` directly in Postman, Insomnia, or a browser.

If you want JSON instead of HTML, send:

```
Accept: application/json

```

Security
--------

[](#security)

The package validates the incoming Meta signature using HMAC-SHA256 before any deletion logic is executed.

Security notes:

- the webhook request is rejected if `signed_request` is malformed
- the payload is rejected if the algorithm is not `HMAC-SHA256`
- the callback is rejected if the computed signature does not match
- the route should **not** be protected by CSRF middleware

By default the package uses the `api` middleware group, which is the recommended setup for webhook endpoints in Laravel applications.

If you move the route under `web` middleware, make sure to exclude it from CSRF protection.

Package Architecture
--------------------

[](#package-architecture)

The package exposes two extension points:

- `Lartisan\FacebookDataDeletion\Contracts\ResolvesFacebookDeletionSubject`
- `Lartisan\FacebookDataDeletion\Contracts\DeletesFacebookDeletionSubjectData`

This lets the host application decide:

- which model is associated with the Meta App-Scoped ID
- where the Facebook identifier is stored
- whether deletion means hard delete, soft delete, anonymization, or a broader cleanup process

License
-------

[](#license)

This package is open-sourced software licensed under the [MIT license](LICENSE).

###  Health Score

39

—

LowBetter than 85% of packages

Maintenance83

Actively maintained with recent releases

Popularity8

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity49

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

Every ~2 days

Total

4

Last Release

86d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/2dcd7882a854e97effa9fbf7c979e9c9c7f9795bfb5422224a22253a10fd0cc0?d=identicon)[cristake](/maintainers/cristake)

---

Top Contributors

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

---

Tags

laravelfacebookmetaprivacydata-deletion

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/lartisan-laravel-facebook-data-deletion/health.svg)

```
[![Health](https://phpackages.com/badges/lartisan-laravel-facebook-data-deletion/health.svg)](https://phpackages.com/packages/lartisan-laravel-facebook-data-deletion)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3345.1M337](/packages/psalm-plugin-laravel)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k14.1M122](/packages/laravel-pulse)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9742.3M121](/packages/roots-acorn)[laravel/cashier

Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services.

2.5k28.4M137](/packages/laravel-cashier)[api-platform/laravel

API Platform support for Laravel

59156.3k11](/packages/api-platform-laravel)

PHPackages © 2026

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