PHPackages                             pdazcom/laravel-referrals - 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. pdazcom/laravel-referrals

ActiveLibrary

pdazcom/laravel-referrals
=========================

A referrals system for a laravel projects.

2.4.0(1mo ago)291.5k13MITPHPPHP ^8.2CI passing

Since Sep 29Pushed 3w ago3 watchersCompare

[ Source](https://github.com/pdazcom/laravel-referrals)[ Packagist](https://packagist.org/packages/pdazcom/laravel-referrals)[ Docs](https://github.com/pdazcom/laravel-referrals)[ RSS](/packages/pdazcom-laravel-referrals/feed)WikiDiscussions master Synced 2d ago

READMEChangelog (10)Dependencies (4)Versions (16)Used By (0)

Simple Referrals system for Laravel
===================================

[](#simple-referrals-system-for-laravel)

[![Latest Version on Packagist](https://camo.githubusercontent.com/421c74bdda05518137df5fa614cb066729998d9d1325fd70a0d5d9116f40f5a2/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7064617a636f6d2f6c61726176656c2d726566657272616c732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/pdazcom/laravel-referrals)[![Software License](https://camo.githubusercontent.com/55c0218c8f8009f06ad4ddae837ddd05301481fcf0dff8e0ed9dadda8780713e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d627269676874677265656e2e7376673f7374796c653d666c61742d737175617265)](LICENSE)[![Tests](https://camo.githubusercontent.com/c662cd535fa24e89915ce5ff7c56a613c80dc9efe7995566da6aeb94336c5e9e/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f7064617a636f6d2f6c61726176656c2d726566657272616c732f74657374732e796d6c3f6272616e63683d6d6173746572266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/pdazcom/laravel-referrals/actions/workflows/tests.yml)[![Total Downloads](https://camo.githubusercontent.com/9abb4f5a97eafb7497a7ecc07120ee5ba7ca02c352086b60c21b166b02f8f647/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f7064617a636f6d2f6c61726176656c2d726566657272616c732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/pdazcom/laravel-referrals)

A simple system of referrals with the ability to assign different programs for different users.

This package was created based on the [lesson](https://blog.damirmiladinov.com/laravel/building-laravel-referral-system.html#.Wc4eA6xJaHo)author is Damir Miladinov, with some minor changes, for which I express my gratitude to him.

- [Installation](#installation)
- [Documentation Map](#documentation-map)
- [Configuration Reference](#configuration-reference)
- [Quickstart](#quickstart)
- [How It Works](#how-it-works)
- [Sharing and Entry Flows](#sharing-and-entry-flows)
- [Reward Hooks](#reward-hooks)
- [Manual Integration Flow](#manual-integration-flow)
- [Bonus](#bonus-content)

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

[](#installation)

These steps are verified against a fresh Laravel 11, Laravel 12, and Laravel 13 application.

### 1. Install the package

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

```
composer require pdazcom/laravel-referrals
```

Laravel registers the service provider automatically through package discovery.

### 2. Publish the config file

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

```
php artisan vendor:publish --tag=referrals-config
```

This creates `config/referrals.php`, where you register your referral program classes.

If you prefer the package command, you can run:

```
php artisan referrals:install --config
```

### 3. Run the migrations

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

```
php artisan migrate
```

The package loads its migrations automatically for the default setup, so you do not need to publish them unless you want to customize the migration files before running them.

If you need to customize the migrations, publish them first:

```
php artisan vendor:publish --tag=referrals-migrations
```

Or use the package command:

```
php artisan referrals:install --migrations
```

### 4. Register the middleware

[](#4-register-the-middleware)

In Laravel 11 and 12, append the middleware to the `web` stack in `bootstrap/app.php`:

```
use Illuminate\Foundation\Configuration\Middleware;

->withMiddleware(function (Middleware $middleware): void {
    $middleware->web(append: [
        \Pdazcom\Referrals\Http\Middleware\StoreReferralCode::class,
    ]);
})
```

This middleware stores referral links in cookies so they can be attached when the user signs up.

It accepts both legacy UUID links and human-friendly referral codes in the same `?ref=` query parameter. For the recommended sharing patterns, see [Sharing and Entry Flows](#sharing-and-entry-flows).

### 5. Add the trait to your user model

[](#5-add-the-trait-to-your-user-model)

Add `Pdazcom\Referrals\Traits\ReferralsMember` to `app/Models/User.php`:

```
use Pdazcom\Referrals\Traits\ReferralsMember;

class User extends Authenticatable
{
    use HasFactory, Notifiable, ReferralsMember;
}
```

### Upgrade notes for older docs

[](#upgrade-notes-for-older-docs)

- If you are upgrading from older README instructions, do not edit `app/Http/Kernel.php` in Laravel 11 or 12. Middleware registration moved to `bootstrap/app.php`.
- You only need to publish the package migrations if you want to edit them before running `php artisan migrate`.

> #### Note
>
> [](#note)
>
> Starting from v2.0, several referral programs can be applied to the same user. They are stored in cookies as a JSON object, and the request instance exposes them in the `_referrals` property:
>
> ```
> [
>    'ref_id_1' => 'expires_timestamp',
>    'ref_id_2' => 'expires_timestamp',
>    ...
>    'ref_id_n' => 'expires_timestamp'
> ]
>
> ```
>
>
>
> `ref_id_n` is the referral link ID, and `expires_timestamp` is the cookie expiration timestamp. Expired links are deleted automatically.

Next: continue with the [quickstart](#quickstart) to create your first referral program and verify the reward flow.

Documentation Map
-----------------

[](#documentation-map)

Use the shortest guide that matches the task you are working on:

DocumentUse it when you need to[README.md](README.md)Install the package, understand the core flow, or verify a first integration[docs/README.md](docs/README.md)Browse the docs by topic instead of searching the repo manually[docs/sharing-and-entry-flows.md](docs/sharing-and-entry-flows.md)Decide between share links, human-friendly codes, and manual code entry[docs/order-subscription-integration.md](docs/order-subscription-integration.md)Reward referrers from order or subscription completion events[docs/fixed-reward-program.md](docs/fixed-reward-program.md)Use or adapt the built-in fixed reward program[CONTRIBUTING.md](CONTRIBUTING.md)Set up a local checkout, run tests, and open a pull request[docs/releases](docs/releases)Review package changes by version[docs/research](docs/research)Read exploratory notes and design directions that are not source-of-truth setup docsConfiguration Reference
-----------------------

[](#configuration-reference)

The package configuration file is `config/referrals.php`:

```
return [
    'programs' => [
        'example' => \Pdazcom\Referrals\Programs\ExampleProgram::class,
    ],
    'fixed_reward_amount' => 10,
    'cookie_name' => 'ref',
    'code_generator' => \Pdazcom\Referrals\Generators\RandomStringCodeGenerator::class,
    'code_length' => 8,
    'code_generation_max_attempts' => 10,
    'prevent_duplicate_rewards' => false,
    'prevent_self_referral' => false,
    'hooks' => [
        'signup' => false,
        'first_purchase' => [
            'enabled'         => false,
            'event'           => null,
            'programs'        => [],
            'user_accessor'   => 'user',
            'reward_accessor' => null,
        ],
    ],
];
```

### Keys

[](#keys)

KeyDefaultRequiredBehavior`programs``['example' => \Pdazcom\Referrals\Programs\ExampleProgram::class]`Yes (for reward execution)Maps `referral_programs.name` to a reward handler class. `RewardUser` resolves handler classes via `config('referrals.programs.')`. Missing mappings are skipped with a warning log.`fixed_reward_amount``10`NoDefault flat reward credited by `Pdazcom\Referrals\Programs\FixedRewardProgram` when you do not override its `FIXED_AMOUNT` constant in a subclass.`cookie_name``'ref'`NoControls the query parameter read by `StoreReferralCode` and the cookie name used to persist active referral link IDs and expiry timestamps.`code_generator``\Pdazcom\Referrals\Generators\RandomStringCodeGenerator::class`NoContainer binding used to generate human-friendly `referral_code` values for new `ReferralLink` records.`code_length``8`NoLength passed to the default random string code generator.`code_generation_max_attempts``10`NoMaximum retries when generating a unique `referral_code` before throwing a `ReferralCodeGenerationException`.`prevent_duplicate_rewards``false`NoWhen enabled, stamps `referral_relationships.rewarded_at` after the first payout and skips later payouts for the same relationship.`prevent_self_referral``false`NoWhen enabled, `ReferUser` skips relationships where the referred user is also the owner of the referral link.`hooks.signup``false`NoWhen `true`, automatically dispatches `UserReferred` on `Illuminate\Auth\Events\Registered`. Requires `StoreReferralCode` on the registration route.`hooks.first_purchase`(see above)NoWhen `enabled` is `true` and `event` is set, automatically dispatches `ReferralCase` when the configured event fires. See [Reward Hooks](#reward-hooks) for full options.### `programs`

[](#programs)

Use `programs` to register each referral program name with the class that should run when `ReferralCase` is dispatched.

- The array key must match the `name` value stored in `referral_programs`.
- The class should implement package program behavior (typically by extending `Pdazcom\Referrals\Programs\AbstractProgram`).
- If no mapping exists for a program name, no reward class is executed for that event.

Example (single program):

```
'programs' => [
    'welcome-bonus' => \App\ReferralPrograms\WelcomeBonusProgram::class,
],
```

Example (multiple programs):

```
'programs' => [
    'welcome-bonus' => \App\ReferralPrograms\WelcomeBonusProgram::class,
    'first-purchase' => \App\ReferralPrograms\FirstPurchaseProgram::class,
],
```

### `cookie_name`

[](#cookie_name)

`cookie_name` defines the referral parameter your links use and the cookie key the middleware writes to.

- With the default value (`ref`), links look like: `/register?ref=ABC123`.
- If you set `cookie_name` to `referral`, links look like: `/register?referral=ABC123`.
- Existing links must use the same query parameter name as your configured `cookie_name`.

### `code_generator`, `code_length`, and `code_generation_max_attempts`

[](#code_generator-code_length-and-code_generation_max_attempts)

Every new `ReferralLink` gets two codes:

- `code`: the legacy UUID used by `$link->link`
- `referral_code`: the human-friendly code used by `$link->referral_link`

The default generator is `Pdazcom\Referrals\Generators\RandomStringCodeGenerator`, which:

- generates uppercase alphanumeric codes
- avoids visually ambiguous characters such as `0`, `O`, `I`, and `1`
- uses `code_length` to determine the generated code size
- retries until the code is unique across both the legacy `code` column and the new `referral_code` column

If you want custom code generation rules, bind a class that implements `Pdazcom\Referrals\Contracts\ReferralCodeGeneratorInterface`:

```
'code_generator' => \App\Referrals\NumericCodeGenerator::class,
```

Use `code_generation_max_attempts` to cap the retry loop if your code space is small or highly constrained.

### `prevent_duplicate_rewards`

[](#prevent_duplicate_rewards)

Enable this guard when a referred user should only produce one payout for a given referral relationship:

```
'prevent_duplicate_rewards' => true,
```

Behavior:

- `RewardUser` locks the matching `referral_relationships` row inside a transaction
- the first successful payout stamps `rewarded_at`
- later `ReferralCase` events for the same relationship are skipped

Run the package migrations before enabling this guard so the `rewarded_at` column exists.

### `prevent_self_referral`

[](#prevent_self_referral)

Enable this guard if users must not attribute themselves with their own referral links:

```
'prevent_self_referral' => true,
```

Behavior:

- `ReferUser` compares the referred user ID with the referral link owner ID
- when they match, the relationship is skipped and a log entry is written
- when disabled, self-referrals behave the same as any other referral

Quickstart
----------

[](#quickstart)

This quickstart gives you a verified path from install to the first successful referral relationship and reward dispatch in a fresh Laravel 11 or 12 app.

### 1. Install the package

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

```
composer require pdazcom/laravel-referrals
php artisan vendor:publish --tag=referrals-config
php artisan migrate
```

You do not need to publish the package migrations for the default setup. The package loads them automatically.

Checkpoint: `php artisan about` should show a `Laravel Referrals` section.

### 2. Register the middleware and trait

[](#2-register-the-middleware-and-trait)

In Laravel 11 and 12, append the middleware in `bootstrap/app.php`:

```
use Illuminate\Foundation\Configuration\Middleware;

->withMiddleware(function (Middleware $middleware): void {
    $middleware->web(append: [
        \Pdazcom\Referrals\Http\Middleware\StoreReferralCode::class,
    ]);
})
```

Then add the trait to your `app/Models/User.php` model:

```
use Pdazcom\Referrals\Traits\ReferralsMember;

class User extends Authenticatable
{
    use HasFactory, Notifiable, ReferralsMember;
}
```

### 3. Add a reward handler

[](#3-add-a-reward-handler)

Create `app/ReferralPrograms/QuickstartProgram.php`:

```
