Skip to content

Commit

Permalink
INIT v2
Browse files Browse the repository at this point in the history
  • Loading branch information
QuentinGab committed Nov 8, 2024
1 parent 0e4ef55 commit 39d9ae0
Show file tree
Hide file tree
Showing 23 changed files with 900 additions and 284 deletions.
129 changes: 111 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,17 @@ php artisan vendor:publish --tag="referrer-config"
This is the content of the published config file:

```php
use Elegantly\Referrer\Enums\Strategy;

return [
/*
|--------------------------------------------------------------------------
| Referrer Sources
|--------------------------------------------------------------------------
|
| These are the classes containing the logic to detect the visitor's referrer.
| You can disable some of them or add as many as you want.
| No matter how many sources you define, they will all be stored.
| These classes contain the logic to detect the visitor's referrer.
| You can disable specific sources or add as many as needed.
| Regardless of the number of sources defined, all values will be stored.
|
*/
'sources' => [
Expand All @@ -54,36 +56,57 @@ return [
\Elegantly\Referrer\Sources\TikTokClickIdSource::class,
],

/*
|--------------------------------------------------------------------------
| Referrer Strategy
|--------------------------------------------------------------------------
|
| Define the strategy for storing referrer values. You can also customize
| the strategy for each source.
|
| 'last' : Stores only the last captured value, ignoring previous ones.
| 'first' : Stores only the first captured value, ignoring subsequent ones.
| 'all' : Stores all captured values.
|
*/
'strategy' => Strategy::All,

/*
|--------------------------------------------------------------------------
| Referrer Drivers
|--------------------------------------------------------------------------
|
| These are the classes containing the logic to store the visitor's referrer.
| By default, they are all disabled. To enable a driver, add a "key" value.
| You can also add your own driver if needed.
| No matter how many drivers you define, they will all store the referrer sources.
| These classes contain the logic to store the visitor's referrer.
| By default, all drivers are disabled. To enable a driver, uncomment it
| or add a custom driver.
|
| Regardless of the number of drivers defined, they will all store
| referrer sources. When accessing referrer data, drivers may be merged,
| with the last driver overwriting the others.
|
| It is recommended to enable at least the Cookie driver for long-term
| storage and the Session driver for immediate storage.
|
*/
'drivers' => [
// \Elegantly\Referrer\Drivers\ContextDriver::class => [
// 'key' => 'referrer',
// ],
// \Elegantly\Referrer\Drivers\SessionDriver::class => [
// 'key' => 'referrer',
// ],
// \Elegantly\Referrer\Drivers\CookieDriver::class => [
// 'key' => Str::slug(env('APP_NAME', 'laravel'), '_').'referrer',
// 'name' => Str::slug(env('APP_NAME', 'laravel'), '_') . '_referrer',
// /**
// * Lifetime in seconds
// * Lifetime in seconds.
// */
// 'lifetime' => 60 * 60 * 24 * 365,
// ],
// \Elegantly\Referrer\Drivers\SessionDriver::class => [
// 'key' => 'referrer',
// ],
// \Elegantly\Referrer\Drivers\ContextDriver::class => [
// 'key' => 'referrer',
// ],
],
];
```

In the file, enable one or more drivers by setting a value for the `key`.
In the file, enable one or more drivers by uncommenting them.

Next, add the `CaptureReferrerMiddleware` to your route:

Expand Down Expand Up @@ -117,12 +140,82 @@ class Kernel extends HttpKernel
}
```

### Handling Multiple Referrers

What if a user encounters multiple referrers during their navigation? For example, a user might have clicked on multiple Google Ads campaigns or links with different UTM parameters.

In the config file, you can define the strategy to adopt for these cases. Here are some examples:

#### Capture the Latest Referrer

```php
use Elegantly\Referrer\Enums\Strategy;
return [
//...
'strategy' => Strategy::Last,
//...
]
```

This will store only the most recent referrer value and discard any previous ones.

#### Capture the First Referrer

```php
use Elegantly\Referrer\Enums\Strategy;
return [
//...
'strategy' => Strategy::First,
//...
]
```

This will store the first referrer value encountered and ignore any subsequent ones.

#### Capture All Referrers

```php
use Elegantly\Referrer\Enums\Strategy;
return [
//...
'strategy' => Strategy::All,
//...
]
```

This will store all referrer values encountered.

### Configuring the Strategy per Source

You can also define a different strategy for each referrer source:

```php
use Elegantly\Referrer\Enums\Strategy;
return [
//...
'strategy' => Strategy::Last, // Global strategy

'sources' => [
\Elegantly\Referrer\Sources\UtmReferrerSource::class => [
'strategy' => Strategy::First, // Custom strategy for UTM referrers
],
\Elegantly\Referrer\Sources\RequestHeaderSource::class,
\Elegantly\Referrer\Sources\GoogleClickIdSource::class,
\Elegantly\Referrer\Sources\MetaClickIdSource::class,
\Elegantly\Referrer\Sources\TikTokClickIdSource::class,
],
//...
]
```

In this example, the global strategy is set to `Strategy::Last`, but for the `UtmReferrerSource`, the strategy is set to `Strategy::First`.

### Retrieving the Visitor Referrer

You can retrieve the referrer sources using the facade:

```php
\Elegantly\Referrer\Facades\Referrer::get(); // Merges all drivers together, with the first one having priority over the next ones
\Elegantly\Referrer\Facades\Referrer::getSources(); // Merges all drivers together, with the last one having priority over the previous ones
\Elegantly\Referrer\Facades\Referrer::getSourcesByDriver(); // Retrieves all driver values
```

Expand All @@ -146,7 +239,7 @@ class RegisteredUserController extends Controller

$user = new User($validated);

$user->referrer = Referrer::get()->get(UtmReferrerSource::class)->utm_source;
$user->referrer = Referrer::getSources()->getFirst(UtmReferrerSource::class)?->utm_source;

$user->save();

Expand Down
53 changes: 38 additions & 15 deletions config/referrer.php
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
<?php

use Elegantly\Referrer\Enums\Strategy;

return [
/*
|--------------------------------------------------------------------------
| Referrer Sources
|--------------------------------------------------------------------------
|
| These are the classes containing the logic to detect the visitor's referrer.
| You can disable some of them or add as many as you want.
| No matter how many sources you define, they will all be stored.
| These classes contain the logic to detect the visitor's referrer.
| You can disable specific sources or add as many as needed.
| Regardless of the number of sources defined, all values will be stored.
|
*/
'sources' => [
Expand All @@ -19,30 +21,51 @@
\Elegantly\Referrer\Sources\TikTokClickIdSource::class,
],

/*
|--------------------------------------------------------------------------
| Referrer Strategy
|--------------------------------------------------------------------------
|
| Define the strategy for storing referrer values. You can also customize
| the strategy for each source.
|
| 'last' : Stores only the last captured value, ignoring previous ones.
| 'first' : Stores only the first captured value, ignoring subsequent ones.
| 'all' : Stores all captured values.
|
*/
'strategy' => Strategy::All,

/*
|--------------------------------------------------------------------------
| Referrer Drivers
|--------------------------------------------------------------------------
|
| These are the classes containing the logic to store the visitor's referrer.
| By default, they are all disabled. To enable a driver, add a "key" value.
| You can also add your own driver if needed.
| No matter how many drivers you define, they will all store the referrer sources.
| These classes contain the logic to store the visitor's referrer.
| By default, all drivers are disabled. To enable a driver, uncomment it
| or add a custom driver.
|
| Regardless of the number of drivers defined, they will all store
| referrer sources. When accessing referrer data, drivers may be merged,
| with the last driver overwriting the others.
|
| It is recommended to enable at least the Cookie driver for long-term
| storage and the Session driver for immediate storage.
|
*/
'drivers' => [
// \Elegantly\Referrer\Drivers\ContextDriver::class => [
// 'key' => 'referrer',
// ],
// \Elegantly\Referrer\Drivers\SessionDriver::class => [
// 'key' => 'referrer',
// ],
// \Elegantly\Referrer\Drivers\CookieDriver::class => [
// 'key' => Str::slug(env('APP_NAME', 'laravel'), '_').'referrer',
// 'name' => Str::slug(env('APP_NAME', 'laravel'), '_') . '_referrer',
// /**
// * Lifetime in seconds
// * Lifetime in seconds.
// */
// 'lifetime' => 60 * 60 * 24 * 365,
// ],
// \Elegantly\Referrer\Drivers\SessionDriver::class => [
// 'key' => 'referrer',
// ],
// \Elegantly\Referrer\Drivers\ContextDriver::class => [
// 'key' => 'referrer',
// ],
],
];
22 changes: 11 additions & 11 deletions src/CaptureReferrerMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,9 @@

use Closure;
use Elegantly\Referrer\Facades\Referrer;
use Elegantly\Referrer\Sources\ReferrerSource;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

/**
* @phpstan-import-type ReferrerSourceArray from \Elegantly\Referrer\Drivers\ReferrerDriver
*/
class CaptureReferrerMiddleware
{
/**
Expand All @@ -31,18 +27,22 @@ public function handle(Request $request, Closure $next): Response

public function getReferrerBySource(Request $request): ReferrerSources
{
$items = new ReferrerSources;
$items = Referrer::getSources();

/**
* @var class-string<ReferrerSource<mixed>>[]
*/
$sources = config('referrer.sources') ?? [];
$sources = Referrer::getSourcesFromConfig();

foreach ($sources as $sourceName) {
$strategy = Referrer::getStrategy($sourceName);
$source = $sourceName::fromRequest($request);

if (! $source->isEmpty()) {
$items->put($source);
if (
$source->isNotEmpty() &&
! $items->has($source)
) {
$items->put(
source: $source,
strategy: $strategy
);
}
}

Expand Down
23 changes: 10 additions & 13 deletions src/Drivers/ContextDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
use Illuminate\Support\Facades\Context;

/**
* @phpstan-import-type ReferrerSourceFullArray from ReferrerSources
* @phpstan-import-type ReferrerSourcesArray from ReferrerSources
*/
class ContextDriver extends ReferrerDriver
{
Expand All @@ -16,33 +16,30 @@ final public function __construct(
//
}

public static function make(): ?static
public static function make(): static
{
if ($key = static::getKeyFromConfig()) {
return new static($key);
}

return null;
return new static(
key: static::getKeyFromConfig()
);
}

public static function getKeyFromConfig(): ?string
public static function getKeyFromConfig(): string
{
/** @var ?string */
return config('referrer.drivers.'.static::class.'.key');
return config()->string('referrer.drivers.'.static::class.'.key');
}

public function put(ReferrerSources $sources): void
{
Context::add(
$this->key,
$sources->toArray()
key: $this->key,
value: $sources->toArray()
);
}

public function get(): ?ReferrerSources
{
/**
* @var null|ReferrerSourceFullArray $sources
* @var null|ReferrerSourcesArray $sources
*/
$sources = Context::get($this->key);

Expand Down
Loading

0 comments on commit 39d9ae0

Please sign in to comment.