diff --git a/README.md b/README.md index 9aac29e..ae5f43a 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,11 @@ # Laravel UTM-Parameters +[![Latest Version on Packagist](https://img.shields.io/packagist/v/suarez/laravel-utm-parameter.svg?style=flat-square)](https://packagist.org/packages/suarez/laravel-utm-parameter) [![StyleCI](https://github.styleci.io/repos/448347178/shield?branch=main)](https://github.styleci.io/repos/448347178?branch=main) [![Test PHP 8.x](https://github.com/toni-suarez/laravel-utm-parameter/actions/workflows/tests-php8.yml/badge.svg?branch=main)](https://github.com/toni-suarez/laravel-utm-parameter/actions/workflows/tests-php8.yml) [![Packagist Downloads](https://img.shields.io/packagist/dt/suarez/laravel-utm-parameter)](https://packagist.org/packages/suarez/laravel-utm-parameter) ![GitHub](https://img.shields.io/github/license/toni-suarez/laravel-utm-parameter) - +[![Statamic Addon](https://img.shields.io/badge/https%3A%2F%2Fstatamic.com%2Faddons%2Ftoni-suarez%2Futm-parameter?style=flat-square&logo=statamic&logoColor=rgb(255%2C%2038%2C%20158)&label=Statamic&link=https%3A%2F%2Fstatamic.com%2Faddons%2Ftoni-suarez%2Futm-parameter)](https://statamic.com/addons/toni-suarez/utm-parameter) A lightweight way to handle UTM parameters session-based in your Laravel Application. @@ -18,34 +19,25 @@ A lightweight way to handle UTM parameters session-based in your Laravel Applica ## Table of Content -- [Introduction](#introduction) - [Installation](#installation) - [Usage](#usage) - [License](#license) -## Introduction - -What are these UTM parameters? UTM is an acronym standing for "Urchin Tracking Module" and where initially introduced in Google Analytics. It's a way, mostly marketers track effectiveness of online marketing campaigns. - -There are five different UTM parameters: -- utm_source -- utm_medium -- utm_campaign -- utm_content -- utm_term - -Not all parameters are used everytime. -Here would be a common example: https://www.example.com/?utm_source=newsletter&utm_medium=email&utm_campaign=holiday-sale - - ## Installation -Install the `utm-parameter` package with composer: +Follow these steps to install the Laravel UTM-Parameters package. -``` +Open your terminal and navigate to your Laravel project directory. Then, use Composer to install the package: + +```bash $ composer require suarez/laravel-utm-parameter ``` +Optionally, you can publish the config file of this package with this command: +```bash +php artisan vendor:publish --tag="utm-parameter" +``` + ### Middleware Open the `app/Http/Kernel.php` file and add a new item to the `web` middleware group: @@ -77,6 +69,87 @@ Route::middleware('utm-parameters') ->get('langing-page/{slug}', 'LandingPageController@show'); ``` +### Use as Facade + +If you prefer not to use it as middleware, you can utilize the UtmParameter Facade directly in your controllers or other parts of your application. Once the `boot($request)`-method is called, you have access to it at any place. For example: + +```php +use Suarez\UtmParameter\Facades\UtmParameter; + +// Inside a controller method +class IndexController { + public function index(Request $request) + { + UtmParameter::boot($request); + } +} + +class SomeDifferentController { + public function index(Request $request) + { + $source = UtmParameter::get('source'); + } +} +``` + +## Configuration + +The configuration file `config/utm-parameter.php` allows you to control the behavior of the UTM parameters handling. + +```php + false, + + /* + * Session Key for UTM Parameters (default: 'utm') + * + * This key specifies the name used to access and store UTM parameters within the session data. + * + * If you're already using 'utm' for another purpose in your application, + * you can customize this key to avoid conflicts. + * Simply provide your preferred key name as a string value. + */ + 'session_key' => 'utm', + + /* + * Allowed UTM Parameters (default: ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'utm_campaign_id']) + * + * This setting defines the UTM parameters that are allowed within your application. + * + * In this array, you can specify a list of allowed UTM parameter names. Each parameter should be listed as a string. + * Only parameters from this list will be stored and processed in the session. + * and any parameter without the 'utm_' prefix will be ignored regardless of its inclusion in this list. + * + * Example: To only allow the basic UTM parameters (source, medium, and campaign), you could update the array like this: + * + * 'allowed_utm_parameters' => [ + * 'utm_source', + * 'utm_medium', + * 'utm_campaign', + * ], + */ + 'allowed_utm_parameters' => [ + 'utm_source', + 'utm_medium', + 'utm_campaign', + 'utm_term', + 'utm_content', + 'utm_campaign_id' + ], +]; +``` + + ## Usage ### All UTM parameters @@ -145,6 +218,103 @@ Simply use: } ``` +### contains_utm() + +You can conditionally show or perform actions based on the presence or absence of a portion of an UTM parameters using contains. + +Simply use: +- `contains_utm('source|medium|campaign|term|content', 'value')` +- `contains_not_utm('source|medium|campaign|term|content', 'value')` + +```blade +@containsUtm('campaign', 'weekly') +
Some Weekly related stuff
+@endhasUtm + +@containsNotUtm('campaign', 'sales') +

Some not Sales stuff

+@endhasNotUtm +``` + +```php + if (contains_utm('campaign', 'weekly')) { + redirect('to/special/page'); + } + + if (contains_not_utm('campaign', 'sale')) { + session()->flash('Did you know, we have a newsletter?'); + } +``` + +## Extending the Middleware + +You can extend the middleware to customize the behavior of accepting UTM parameters. For example, you can override the `shouldAcceptUtmParameter` method. + +First, create a new middleware using Artisan: + +```bash +php artisan make:middleware CustomMiddleware +``` + +Then, update the new middleware to extend UtmParameters and override the `shouldAcceptUtmParameter` method: + +```php +isMethod('GET') || $request->isMethod('POST'); + } +} +``` + +Finally, update your `app/Http/Kernel.php` to **replace** the `UtmParameters` with `CustomMiddleware`: + +```php +# app/Http/Kernel.php +use App\Http\Middleware\CustomMiddleware; + +protected $middlewareGroups = [ + 'web' => [ + /* ... keep the existing middleware here */ + CustomMiddleware::class, + ], +]; +``` + +## Resources +Explore additional use cases and resources on the [wiki pages](https://github.com/toni-suarez/laravel-utm-parameter/wiki) + +- [Installation Guide](https://github.com/toni-suarez/laravel-utm-parameter/wiki/Installation-Guide) +- [Installation Guide (Laravel 8.x to 10.x)](https://github.com/toni-suarez/laravel-utm-parameter/wiki/Installation-Guide-(Laravel-8.x-to-10.x)) +- [How it works](https://github.com/toni-suarez/laravel-utm-parameter/wiki/How-it-works) +- [Limitations](https://github.com/toni-suarez/laravel-utm-parameter/wiki/Limitations) +- [Advanced Usage](https://github.com/toni-suarez/laravel-utm-parameter/wiki/Advanced-Usage) +- [Blade Usage](https://github.com/toni-suarez/laravel-utm-parameter/wiki/Blade-Usage) +- [Usage via Facade or Helper Class](https://github.com/toni-suarez/laravel-utm-parameter/wiki/Usage-via-Facade-or-Helper-Class) + +### Inspirations +- [Use Case: A/B Testing](https://github.com/toni-suarez/laravel-utm-parameter/wiki/Use-Case:-A-B-Testing) +- [Use Case: Different Styles for Social Media](https://github.com/toni-suarez/laravel-utm-parameter/wiki/Use-Case:-Different-Styles-for-Social-Media) +- [Use Case: Lead Attribution](https://github.com/toni-suarez/laravel-utm-parameter/wiki/Use-Case:-Lead-Attribution) +- [Use Case: Social Media Tracking](https://github.com/toni-suarez/laravel-utm-parameter/wiki/Use-Case:-Social-Media-Tracking) +- [Use‐Case: Newsletter Redirect on Product Detail Page](https://github.com/toni-suarez/laravel-utm-parameter/wiki/Use%E2%80%90Case:-Newsletter-Redirect-on-Product-Detail-Page) +- [Use‐Case: Offline Marketing Integration](https://github.com/toni-suarez/laravel-utm-parameter/wiki/Use%E2%80%90Case:-Offline-Marketing-Integration) + --- ## License diff --git a/composer.json b/composer.json index 8646d87..8052cdb 100644 --- a/composer.json +++ b/composer.json @@ -3,6 +3,13 @@ "description": "A little helper to store and handle utm-parameter", "homepage": "https://github.com/toni-suarez/laravel-utm-parameter", "license": "MIT", + "keywords": [ + "php", + "laravel", + "utm-parameter", + "social-media", + "utm" + ], "authors": [ { "name": "Toni Suarez", @@ -44,7 +51,10 @@ "laravel": { "providers": [ "Suarez\\UtmParameter\\Providers\\UtmParameterServiceProvider" - ] + ], + "aliases": { + "UtmParameter": "Suarez\\UtmParameter\\Facades\\UtmParameter" + } } }, "minimum-stability": "stable", diff --git a/src/Facades/UtmParameter.php b/src/Facades/UtmParameter.php new file mode 100644 index 0000000..ef7f39c --- /dev/null +++ b/src/Facades/UtmParameter.php @@ -0,0 +1,26 @@ +shouldAcceptUtmParameter($request)) { - app(UtmParameter::class)->boot(session('utm')); + UtmParameter::boot($request); } return $next($request); @@ -29,9 +29,8 @@ public function handle(Request $request, Closure $next) * Determines whether the given request/response pair should accept UTM-Parameters. * * @param \Illuminate\Http\Request $request - * @param \Illuminate\Http\Response $response * - * @return \Illuminate\Http\Request + * @return bool */ protected function shouldAcceptUtmParameter(Request $request) { diff --git a/src/Providers/UtmParameterServiceProvider.php b/src/Providers/UtmParameterServiceProvider.php index dc72e12..4a61591 100644 --- a/src/Providers/UtmParameterServiceProvider.php +++ b/src/Providers/UtmParameterServiceProvider.php @@ -15,9 +15,8 @@ class UtmParameterServiceProvider extends ServiceProvider */ public function register() { - $this->app->singleton(UtmParameter::class, function () { - return new UtmParameter(); - }); + $this->app->singleton(UtmParameter::class, fn () => new UtmParameter()); + $this->mergeConfigFrom(__DIR__.'/../config/utm-parameter.php', 'utm-parameter'); } /** @@ -27,6 +26,8 @@ public function register() */ public function boot() { + $this->publishes([__DIR__.'/../config/utm-parameter.php' => config_path('utm-parameter.php')], 'utm-parameter'); + Blade::if('hasUtm', function (string $key, string|null $value = null) { return has_utm($key, $value); }); @@ -34,5 +35,15 @@ public function boot() Blade::if('hasNotUtm', function (string $key, string|null $value = null) { return has_not_utm($key, $value); }); + + Blade::if('containsUtm', function (string $key, string|null $value = null) { + return contains_utm($key, $value); + }); + + Blade::if('containsNotUtm', function (string $key, string|null $value = null) { + return contains_not_utm($key, $value); + }); + + AliasLoader::getInstance()->alias('UtmParameter', \Suarez\UtmParameter\Facades\UtmParameter::class); } } diff --git a/src/UtmParameter.php b/src/UtmParameter.php index 7c21669..cc3b502 100644 --- a/src/UtmParameter.php +++ b/src/UtmParameter.php @@ -2,6 +2,8 @@ namespace Suarez\UtmParameter; +use Illuminate\Http\Request; + class UtmParameter { /** @@ -9,34 +11,58 @@ class UtmParameter * * @var array */ - public $parameters; + public array|null $parameters; + + /** + * Utm Parameter Session Key. + * + * @var string + */ + public string $sessionKey; + - public function __construct($parameters = []) + public function __construct(array $parameters = []) { - $this->parameters = is_string($parameters) - ? json_decode($parameters, true) - : $parameters; + $this->sessionKey = config('utm-parameter.session_key'); + $this->parameters = $parameters; } /** * Bootstrap UtmParameter. * - * @param array|string|null $parameters + * @param Request $request * * @return UtmParameter */ - public function boot($parameters = null) + public function boot(Request $request) + { + $this->parameters = $this->useRequestOrSession($request); + return $this; + } + + /** + * Check which Parameters should be used. + * + * @param \Illuminate\Http\Request $request + * @return array + */ + public function useRequestOrSession(Request $request) { - if (!$parameters) { - $parameters = self::getParameter(); - session(['utm' => $parameters]); + $currentRequestParameter = $this->getParameter($request); + $sessionParameter = session($this->sessionKey); + + if (!empty($currentRequestParameter) && empty($sessionParameter)) { + session([$this->sessionKey => $currentRequestParameter]); + return $currentRequestParameter; } - $this->parameters = is_string($parameters) - ? json_decode($parameters, true) - : $parameters; + if (!empty($currentRequestParameter) && !empty($sessionParameter) && config('utm-parameter.override_utm_parameters')) { + $mergedParameters = array_merge($sessionParameter, $currentRequestParameter); + session([$this->sessionKey => $mergedParameters]); + return $mergedParameters; + } - return app(UtmParameter::class, $parameters); + return $sessionParameter; } /** @@ -44,9 +70,9 @@ public function boot($parameters = null) * * @return array */ - public static function all() + public function all() { - return app(UtmParameter::class)->parameters ?? []; + return $this->parameters ?? []; } /** @@ -56,13 +82,10 @@ public static function all() * * @return string|null */ - public static function get($key) + public function get(string $key) { - $parameters = self::all(); - - if (strpos($key, 'utm_') === false) { - $key = 'utm_'.$key; - } + $parameters = $this->all(); + $key = $this->ensureUtmPrefix($key); if (!array_key_exists($key, $parameters)) { return null; @@ -79,22 +102,50 @@ public static function get($key) * * @return bool */ - public static function has($key, $value = null) + public function has(string $key, $value = null) { - $parameters = self::all(); - - if (strpos($key, 'utm_') === false) { - $key = 'utm_'.$key; - } + $parameters = $this->all(); + $key = $this->ensureUtmPrefix($key); if (!array_key_exists($key, $parameters)) { return false; } if (array_key_exists($key, $parameters) && $value !== null) { - return self::get($key) === $value; + return $this->get($key) === $value; + } + + return true; + } + + /** + * Determine if a value contains inside the key. + * + * @param string $key + * @param string $value + * @return bool + */ + public function contains(string $key, string $value) + { + $parameters = $this->all(); + $key = $this->ensureUtmPrefix($key); + + if (!array_key_exists($key, $parameters) || !is_string($value)) { + return false; } + return str_contains($this->get($key), $value); + } + + /** + * Clear and remove utm session. + * + * @return bool + */ + public function clear() + { + session()->forget($this->sessionKey); + $this->parameters = null; return true; } @@ -103,11 +154,29 @@ public static function has($key, $value = null) * * @return array */ - protected static function getParameter() + protected function getParameter(Request $request) { - return collect(request()->all()) + $allowedKeys = config('utm-parameter.allowed_utm_parameters', [ + 'utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content' + ]); + + return collect($request->all()) ->filter(fn ($value, $key) => substr($key, 0, 4) === 'utm_') - ->map(fn ($value) => htmlspecialchars($value, ENT_QUOTES, 'UTF-8')) + ->filter(fn ($value, $key) => in_array($key, $allowedKeys)) + ->mapWithKeys(fn ($value, $key) => [ + htmlspecialchars($key, ENT_QUOTES, 'UTF-8') => htmlspecialchars($value, ENT_QUOTES, 'UTF-8') + ]) ->toArray(); } + + /** + * Ensure the key to start with 'utm_'. + * + * @param string $key + * @return string + */ + protected function ensureUtmPrefix(string $key): string + { + return str_starts_with($key, 'utm_') ? $key : 'utm_' . $key; + } } diff --git a/src/config/utm-parameter.php b/src/config/utm-parameter.php new file mode 100644 index 0000000..0e5fb44 --- /dev/null +++ b/src/config/utm-parameter.php @@ -0,0 +1,50 @@ + false, + + /* + * Session Key for UTM Parameters (default: 'utm') + * + * This key specifies the name used to access and store UTM parameters within the session data. + * + * If you're already using 'utm' for another purpose in your application, + * you can customize this key to avoid conflicts. + * Simply provide your preferred key name as a string value. + */ + 'session_key' => 'utm', + + /* + * Allowed UTM Parameters (default: ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'utm_campaign_id']) + * + * This setting defines the UTM parameters that are allowed within your application. + * + * In this array, you can specify a list of allowed UTM parameter names. Each parameter should be listed as a string. + * Only parameters from this list will be stored and processed in the session. + * and any parameter without the 'utm_' prefix will be ignored regardless of its inclusion in this list. + * + * Example: To only allow the basic UTM parameters (source, medium, and campaign), you could update the array like this: + * + * 'allowed_utm_parameters' => [ + * 'utm_source', + * 'utm_medium', + * 'utm_campaign', + * ], + */ + 'allowed_utm_parameters' => [ + 'utm_source', + 'utm_medium', + 'utm_campaign', + 'utm_term', + 'utm_content', + 'utm_campaign_id' + ], +]; diff --git a/src/helper.php b/src/helper.php index 1c61eb0..2bbf8c7 100644 --- a/src/helper.php +++ b/src/helper.php @@ -1,6 +1,6 @@ sessionKey = Config::get('utm-parameter.session_key'); $parameters = [ 'utm_source' => 'google', @@ -19,13 +25,51 @@ public function setUp(): void 'utm_term' => '{targetid}', ]; - app()->bind(UtmParameter::class, function () use ($parameters) { - return new UtmParameter($parameters); - }); + $request = Request::create('/test', 'GET', $parameters); + + UtmParameter::boot($request); + } + + public function tearDown() : void + { + session()->forget($this->sessionKey); + + Config::set('utm-parameter.override_utm_parameters', null); + Config::set('utm-parameter.session_key', null); + + parent::tearDown(); + } + + public function test_it_should_be_bound_in_the_app() + { + $utm = app(UtmParameter::class); + $this->assertInstanceOf(UtmParameter::class, $utm); + } + + public function test_it_should_have_a_session_key() + { + $this->assertIsString($this->sessionKey); + } + + public function test_it_should_have_a_session() + { + $sessionContent = session($this->sessionKey); + $this->assertIsArray($sessionContent); + $this->assertArrayHasKey('utm_source', $sessionContent); + $this->assertIsNotString(session($this->sessionKey)); + } + + public function test_it_should_also_clear_a_session() + { + $sessionContent = session($this->sessionKey); + $this->assertIsArray($sessionContent); + + $sessionEmptyContent = session()->forget($this->sessionKey); + $this->assertIsNotArray($sessionEmptyContent); + $this->assertNull($sessionEmptyContent); } - /** @test */ - public function it_should_have_an_utm_attribute_bag() + public function test_it_should_have_an_utm_attribute_bag() { $utm = UtmParameter::all(); $this->assertIsArray($utm); @@ -33,123 +77,363 @@ public function it_should_have_an_utm_attribute_bag() $this->assertArrayHasKey('utm_source', $utm); } - /** @test */ - public function it_should_have_a_source_parameter() + public function test_it_should_have_a_source_parameter() { $source = UtmParameter::get('source'); $this->assertNotEmpty($source); + $this->assertIsString($source); $this->assertEquals('google', $source); } - /** @test */ - public function it_should_have_work_with_utm_inside_key() + public function test_it_should_have_work_with_utm_inside_key() { $source = UtmParameter::get('utm_source'); $this->assertNotEmpty($source); + $this->assertIsString($source); $this->assertEquals('google', $source); } - /** @test */ - public function it_should_have_a_medium_parameter() + public function test_it_should_have_a_medium_parameter() { $medium = UtmParameter::get('medium'); $this->assertNotEmpty($medium); + $this->assertIsString($medium); $this->assertEquals('cpc', $medium); } - /** @test */ - public function it_should_have_a_campaign_parameter() + public function test_it_should_have_a_campaign_parameter() { $campaign = UtmParameter::get('campaign'); $this->assertNotEmpty($campaign); + $this->assertIsString($campaign); $this->assertEquals('{campaignid}', $campaign); } - /** @test */ - public function it_should_have_a_content_parameter() + public function test_it_should_have_a_content_parameter() { $content = UtmParameter::get('content'); $this->assertNotEmpty($content); + $this->assertIsString($content); $this->assertEquals('{adgroupid}', $content); } - /** @test */ - public function it_should_have_a_term_parameter() + public function test_it_should_have_a_term_parameter() { $term = UtmParameter::get('term'); $this->assertNotEmpty($term); + $this->assertIsString($term); $this->assertEquals('{targetid}', $term); } - /** @test */ - public function it_should_get_a_utm_parameter_via_helper() + public function test_it_should_get_a_utm_parameter_via_helper() { $source = get_utm('source'); $this->assertNotEmpty($source); + $this->assertIsString($source); $this->assertEquals('google', $source); } - /** @test */ - public function it_should_determine_if_utm_has_key() + public function test_it_should_determine_if_utm_has_key() { $hasSource = UtmParameter::has('source'); $this->assertIsBool($hasSource); + $this->assertNotEmpty($hasSource); $this->assertTrue($hasSource); } - /** @test */ - public function it_should_determine_if_utm_has_not_key() + public function test_it_should_determine_if_utm_has_not_key() { $hasRandomKey = UtmParameter::has('random-key'); $this->assertIsBool($hasRandomKey); + $this->assertEmpty($hasRandomKey); $this->assertFalse($hasRandomKey); } - /** @test */ - public function it_should_determine_if_utm_has_key_and_value() + public function test_it_should_determine_if_utm_has_key_and_value() { $hasGoogleSource = UtmParameter::has('utm_source', 'google'); $this->assertIsBool($hasGoogleSource); + $this->assertNotEmpty($hasGoogleSource); $this->assertTrue($hasGoogleSource); } - /** @test */ - public function it_should_determine_if_utm_has_not_key_and_value() + public function test_it_should_determine_if_utm_has_not_key_and_value() { $hasRandomSource = UtmParameter::has('random-source', 'random-value'); $this->assertIsBool($hasRandomSource); + $this->assertEmpty($hasRandomSource); $this->assertFalse($hasRandomSource); } - /** @test */ - public function it_should_determine_if_a_key_exists_for_utm_parameters() + public function test_it_should_determine_if_a_key_exists_for_utm_parameters() { $hasSource = has_utm('source'); $this->assertIsBool($hasSource); + $this->assertNotEmpty($hasSource); $this->assertTrue($hasSource); } - /** @test */ - public function it_should_determine_if_a_utm_parameter_equals_a_value() + public function test_it_should_determine_if_a_utm_parameter_equals_a_value() { $isGoogle = has_utm('source', 'google'); $this->assertIsBool($isGoogle); + $this->assertNotEmpty($isGoogle); $this->assertTrue($isGoogle); } - /** @test */ - public function it_should_determine_if_a_key_does_not_exists_for_utm_parameters() + public function test_it_should_determine_if_a_key_does_not_exists_for_utm_parameters() { $hasRandomKey = has_not_utm('random-key'); $this->assertIsBool($hasRandomKey); + $this->assertNotEmpty($hasRandomKey); $this->assertTrue($hasRandomKey); } - /** @test */ - public function it_should_determine_if_a_utm_parameter_not_equals_a_value() + public function test_it_should_determine_if_a_utm_parameter_not_equals_a_value() { $isRandomSource = has_not_utm('source', 'random'); $this->assertIsBool($isRandomSource); + $this->assertNotEmpty($isRandomSource); $this->assertTrue($isRandomSource); } + + public function test_it_should_determine_if_an_utm_contains_a_value() + { + $campaign = UtmParameter::contains('utm_campaign', 'campaign'); + $this->assertIsBool($campaign); + $this->assertNotEmpty($campaign); + $this->assertTrue($campaign); + } + + public function test_it_should_determine_if_an_utm_contains_not_a_value() + { + $hasRandomCampaign = UtmParameter::contains('utm_campaign', 'some-thing'); + $this->assertIsBool($hasRandomCampaign); + $this->assertEmpty($hasRandomCampaign); + $this->assertFalse($hasRandomCampaign); + } + + public function test_it_should_determine_if_an_utm_contains_a_non_string_value() + { + $campaign = UtmParameter::contains('utm_campaign', 'null'); + $this->assertIsBool($campaign); + $this->assertFalse($campaign); + + $term = UtmParameter::contains('utm_term', 'false'); + $this->assertIsBool($term); + $this->assertFalse($term); + + $content = UtmParameter::contains('utm_content', '[]'); + $this->assertIsBool($content); + $this->assertFalse($content); + + $medium = UtmParameter::contains('utm_medium', '1'); + $this->assertIsBool($medium); + $this->assertFalse($medium); + } + + public function test_it_should_determine_if_a_utm_parameter_contains_a_value() + { + $isGoogle = contains_utm('source', 'goog'); + $this->assertIsBool($isGoogle); + $this->assertTrue($isGoogle); + } + + public function test_it_should_determine_if_a_utm_parameter_not_contains_a_value() + { + $isRandomSource = has_not_utm('source', 'random'); + $this->assertIsBool($isRandomSource); + $this->assertTrue($isRandomSource); + } + + public function test_it_should_clear_and_remove_the_utm_parameter_again() + { + $source = UtmParameter::get('source'); + $this->assertEquals('google', $source); + $this->assertArrayHasKey('utm_source', session($this->sessionKey)); + + UtmParameter::clear(); + $emptySource = UtmParameter::get('source'); + $this->assertNull(session($this->sessionKey)); + $this->assertNull($emptySource); + } + + public function test_it_should_overwrite_new_utm_parameter() + { + Config::set('utm-parameter.override_utm_parameters', true); + + $source = UtmParameter::get('source'); + $this->assertEquals('google', $source); + + $parameters = [ + 'utm_source' => 'newsletter', + 'utm_medium' => 'email' + ]; + + $request = Request::create('/', 'GET', $parameters); + UtmParameter::boot($request); + + $source = UtmParameter::get('source'); + $this->assertEquals('newsletter', $source); + + $medium = UtmParameter::get('utm_medium'); + $this->assertEquals('email', $medium); + + $campaign = UtmParameter::get('campaign'); + $this->assertEquals('{campaignid}', $campaign); + } + + public function test_it_should_keep_existing_parameters() + { + Config::set('utm-parameter.override_utm_parameters', false); + + $source = UtmParameter::get('source'); + $this->assertEquals('google', $source); + + $parameters = [ + 'id' => '0123456789', + 'sorting' => 'relevance' + ]; + + $request = Request::create('/test', 'GET', $parameters); + UtmParameter::boot($request); + + $id = UtmParameter::get('id'); + $this->assertEmpty($id); + $this->assertNull($id); + + $sorting = UtmParameter::get('sorting'); + $this->assertEmpty($sorting); + $this->assertNull($sorting); + + $source = UtmParameter::get('source'); + $this->assertEquals('google', $source); + + $medium = UtmParameter::get('utm_medium'); + $this->assertEquals('cpc', $medium); + + $campaign = UtmParameter::get('campaign'); + $this->assertEquals('{campaignid}', $campaign); + } + + public function test_it_should_keep_existing_parameters_while_browsing() + { + $source = UtmParameter::get('source'); + $this->assertEquals('google', $source); + + $parameters = ['id' => '0123456789', 'sorting' => 'relevance']; + $request = Request::create('/new-page', 'GET', $parameters); + UtmParameter::boot($request); + + $id = UtmParameter::get('id'); + $this->assertEmpty($id); + $this->assertNull($id); + + $sorting = UtmParameter::get('sorting'); + $this->assertEmpty($sorting); + $this->assertNull($sorting); + + $source = UtmParameter::get('source'); + $this->assertEquals('google', $source); + + $parameters = []; + $request = Request::create('/second-page', 'GET', $parameters); + UtmParameter::boot($request); + + $id = UtmParameter::get('id'); + $this->assertEmpty($id); + $this->assertNull($id); + + $sorting = UtmParameter::get('sorting'); + $this->assertEmpty($sorting); + $this->assertNull($sorting); + + $source = UtmParameter::get('source'); + $this->assertEquals('google', $source); + } + + public function test_it_should_only_use_utm_parameters_in_the_allowed_list() + { + session()->forget($this->sessionKey); + Config::set('utm-parameter.override_utm_parameters', true); + Config::set('utm-parameter.allowed_utm_parameters', ['utm_source', 'utm_medium']); + + $parameters = [ + 'utm_source'=> 'newsletter', + 'utm_medium' => 'email', + 'utm_campaign' => 'not-allowed' + ]; + + $request = Request::create('/test', 'GET', $parameters); + UtmParameter::boot($request); + + $source = UtmParameter::get('source'); + $this->assertEquals('newsletter', $source); + $this->assertIsNotInt($source); + $this->assertNotEmpty($source); + + $medium = UtmParameter::get('medium'); + $this->assertEquals('email', $medium); + $this->assertIsNotInt($medium); + $this->assertNotEmpty($medium); + + $campaign = UtmParameter::get('campaign'); + $this->assertNull($campaign); + $this->assertEmpty($campaign); + + $term = UtmParameter::get('term'); + $this->assertNull($term); + $this->assertEmpty($term); + + $utm_campaign_id = UtmParameter::get('utm_campaign_id'); + $this->assertNull($utm_campaign_id); + $this->assertEmpty($utm_campaign_id); + } + + public function test_it_should_sanitize_utm_parameter() + { + Config::set('utm-parameter.override_utm_parameters', true); + + $parameters = [ + 'utm_source'=> 'google', + 'utm_medium' => 'cpc', + 'utm_campaign' => '