PHPackages                             lalalili/campaign-kit - 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. lalalili/campaign-kit

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

lalalili/campaign-kit
=====================

Reusable campaign pages with configurable GA4 tracking and preview generation for Laravel.

v0.1.2(2mo ago)101proprietaryPHPPHP ^8.4

Since Feb 28Pushed 2mo agoCompare

[ Source](https://github.com/lalalili/campaign-kit)[ Packagist](https://packagist.org/packages/lalalili/campaign-kit)[ RSS](/packages/lalalili-campaign-kit/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (11)Versions (3)Used By (1)

lalalili/campaign-kit
=====================

[](#lalalilicampaign-kit)

Reusable campaign page toolkit for Laravel projects.

This package provides:

- Stable campaign frontend routes (preview / slug / id)
- Config-driven campaign layout preview factory
- GA4 tracking driver layer (`data_layer`, `gtag`, `null`)
- Preview image generation command (Playwright PNG + Imagick WebP)
- Contracts for host-project adapters (repository, pricing, images, CTA)

Scope
-----

[](#scope)

In package scope:

- Campaign route/controller orchestration
- Preview skeleton rendering and preview asset generation flow
- Tracking config normalization and JS runtime API contract
- Extension contracts for host adapters

Out of package scope (host app adapter layer):

- Eloquent query logic and domain authorization
- Product/event pricing/image lookup details
- Cart/CTA business flow implementation
- Admin UI implementation

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

[](#requirements)

- PHP `^8.4`
- Laravel `^12.0`
- `ext-imagick` (for WebP conversion)
- Node.js runtime (for preview capture script)

Install
-------

[](#install)

### Option A: Local path repository

[](#option-a-local-path-repository)

In app `composer.json`:

```
{
  "repositories": [
    {
      "type": "path",
      "url": "packages/campaign-kit",
      "options": {
        "symlink": true
      }
    }
  ],
  "require": {
    "lalalili/campaign-kit": "^0.1"
  }
}
```

Then run:

```
composer update lalalili/campaign-kit
```

### Option B: Private VCS repository

[](#option-b-private-vcs-repository)

In app `composer.json`:

```
{
  "repositories": [
    {
      "type": "vcs",
      "url": "git@github.com:lalalili/campaign-kit.git"
    }
  ],
  "require": {
    "lalalili/campaign-kit": "^0.1"
  }
}
```

Then run:

```
composer update lalalili/campaign-kit
```

Laravel Setup
-------------

[](#laravel-setup)

Auto-discovery loads `CampaignKitServiceProvider`.

Install publishable resources:

```
php artisan campaign-kit:install
```

Publish tags manually if needed:

- `campaign-kit-config`
- `campaign-kit-views`
- `campaign-kit-assets`
- `campaign-kit-bin`
- `campaign-kit-stubs`

`campaign-kit-assets` also publishes the default preview book thumbnail to:

- `public/vendor/campaign-kit/images/default-book-thumbnail.svg`

Default Routes
--------------

[](#default-routes)

When `config('campaign-kit.routes.enabled') === true`, these routes are registered:

- `GET /campaign/layout-preview/{type}/{variant}` → `campaign.layout-preview`
- `GET /campaign/s/{slug}` → `campaign.show.slug`
- `GET /campaign/{campaignId}` → `campaign.show.id`

Host Adapter Contracts
----------------------

[](#host-adapter-contracts)

Bind these contracts in host app:

- `CampaignRepositoryContract`
- `CampaignLayoutResolverContract`
- `CampaignPriceResolverContract`
- `CampaignImageResolverContract`
- `CampaignCtaAdapterContract`

If host does not bind them, package falls back to null/default adapters.

JavaScript API
--------------

[](#javascript-api)

Global API contract:

- `window.CampaignKit.initType1(config)`
- `window.CampaignKit.setTracker(driver, options)`

Supported tracking drivers:

- `data_layer` (default)
- `gtag`
- `null`

Driver and event mapping come from `config('campaign-kit.tracking')`.

GA4 Configuration &amp; Usage
-----------------------------

[](#ga4-configuration--usage)

### 1) Configure tracking driver and event mapping

[](#1-configure-tracking-driver-and-event-mapping)

`config/campaign-kit.php`:

```
'tracking' => [
    'enabled'             => true,
    'driver'              => 'data_layer', // data_layer | gtag | null
    'data_layer_name'     => 'dataLayer',
    'gtag_measurement_id' => env('GA4_MEASUREMENT_ID'),
    'currency'            => 'TWD',
    'affiliation'         => 'My Store',
    'event_map'           => [
        'view_promotion'   => 'view_promotion',
        'select_promotion' => 'select_promotion',
        'select_item'      => 'select_item',
        'add_to_cart'      => 'add_to_cart',
    ],
],
```

### 2) Pass tracking config to frontend runtime

[](#2-pass-tracking-config-to-frontend-runtime)

In host campaign view script:

```

    window.__CAMPAIGN_KIT__ = {
        ...(window.__CAMPAIGN_KIT__ || {}),
        tracking: @json($campaignTrackingConfig ?? []),
    };

    window.CampaignKit?.setTracker?.(
        window.__CAMPAIGN_KIT__.tracking?.driver || 'data_layer',
        window.__CAMPAIGN_KIT__.tracking || {}
    );

    window.CampaignKit?.initType1?.({
        campaignId: @js((string) $campaign->id),
        campaignName: @js((string) $campaign->campaign_title),
        currency: window.__CAMPAIGN_KIT__.tracking?.currency || 'TWD',
        affiliation: window.__CAMPAIGN_KIT__.tracking?.affiliation || '',
    });

```

### 3) Event behavior

[](#3-event-behavior)

Type1 runtime will emit:

- `view_promotion`
- `select_promotion`
- `select_item`
- `add_to_cart`

When `tracking.enabled = false` or driver is `null`, tracking becomes no-op.

Commands
--------

[](#commands)

### Install package resources

[](#install-package-resources)

```
php artisan campaign-kit:install
```

### Scaffold a new layout type

[](#scaffold-a-new-layout-type)

```
php artisan campaign-kit:scaffold-layout 2 --slug=summer-sale
```

Generates:

- `resources/views/campaigns/type{type}.blade.php`
- `resources/views/campaigns/type{type}_mobile.blade.php`
- `resources/views/campaigns/previews/type{type}.blade.php`
- `resources/views/campaigns/previews/type{type}_mobile.blade.php`
- `public/css/campaigns/type{type}.css`
- `public/css/campaigns/type{type}_mobile.css`
- `resources/js/campaign-type{type}.js`
- updates `campaign-kit-layouts.php`

### Generate preview WebP images

[](#generate-preview-webp-images)

```
php artisan campaign-kit:generate-layout-previews --base-url=https://example.test
```

Useful options:

- `--type=1 --type=2` or comma-separated
- `--variant=desktop,mobile`
- `--keep-on-fail` (do not overwrite valid existing WebP on capture failure)

Output filename convention:

- `{slug}.webp`
- `{slug}-mobile.webp`

Layout Thumbnail Generation
---------------------------

[](#layout-thumbnail-generation)

### 1) Configure preview generation

[](#1-configure-preview-generation)

`config/campaign-kit.php`:

```
'routes' => [
    'preview_path_template' => '/campaign/layout-preview/{type}/{variant}',
],

'preview' => [
    'wait_for_selector'   => '.campaign-preview-root',
    'ignore_https_errors' => false,
    'output_dir'          => public_path('campaign/layouts'),
    'default_item_image'  => '/vendor/campaign-kit/images/default-book-thumbnail.svg',
    'variants'            => [
        'desktop' => ['width' => 1366, 'height' => 1024],
        'mobile'  => ['width' => 430, 'height' => 932],
    ],
    'types_file'          => base_path('campaign-kit-layouts.php'),
],
```

### 2) Runtime requirements for generation

[](#2-runtime-requirements-for-generation)

- Node.js available in shell PATH
- Playwright installed (`npm i -D playwright` + `npx playwright install chromium`)
- PHP `ext-imagick` enabled

### 3) Generate images

[](#3-generate-images)

```
php artisan campaign-kit:generate-layout-previews --base-url=https://example.test
```

Common examples:

```
# only type 1 desktop
php artisan campaign-kit:generate-layout-previews --type=1 --variant=desktop

# multiple types
php artisan campaign-kit:generate-layout-previews --type=1 --type=2 --variant=desktop,mobile

# keep existing webp when capture fails
php artisan campaign-kit:generate-layout-previews --keep-on-fail
```

The command flow is:

1. Open preview route (`/campaign/layout-preview/{type}/{variant}`)
2. Capture PNG by Playwright (`bin/capture-campaign-layout-preview.mjs`)
3. Convert PNG to WebP by Imagick

Preview Pipeline
----------------

[](#preview-pipeline)

1. Open preview route URL (`/campaign/layout-preview/{type}/{variant}`)
2. Capture PNG via Playwright script (`bin/capture-campaign-layout-preview.mjs`)
3. Convert PNG to WebP via Imagick

Config
------

[](#config)

Main config file: `config/campaign-kit.php`

Key sections:

- `redirect`
- `routes`
- `tracking`
- `preview`

You can also externalize preview type mapping via:

- `preview.types_file` (default `base_path('campaign-kit-layouts.php')`)

Testing Scope
-------------

[](#testing-scope)

Package tests cover package-level behavior:

- Preview routes and placeholder behavior
- Frontend controller context/redirect behavior
- Preview factory and resolver behavior
- Tracking config normalization
- Generate preview command and `--keep-on-fail`

Host app tests should cover integration behavior:

- Contract bindings to app adapters
- Route compatibility and controller mapping
- View/DOM/JS compatibility with project-specific templates
- End-to-end domain flows

Local Quality Checks
--------------------

[](#local-quality-checks)

Inside package directory:

```
composer install
composer test
composer analyse
```

###  Health Score

36

—

LowBetter than 82% of packages

Maintenance86

Actively maintained with recent releases

Popularity2

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity42

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 ~1 days

Total

2

Last Release

71d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/6d12612270f160b9b015d603ed637f88cfc5edd78f2e287b29ac9ae22a71e8f1?d=identicon)[lalalili](/maintainers/lalalili)

---

Top Contributors

[![lalalili](https://avatars.githubusercontent.com/u/7522570?v=4)](https://github.com/lalalili "lalalili (3 commits)")

###  Code Quality

TestsPest

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/lalalili-campaign-kit/health.svg)

```
[![Health](https://phpackages.com/badges/lalalili-campaign-kit/health.svg)](https://phpackages.com/packages/lalalili-campaign-kit)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3274.9M308](/packages/psalm-plugin-laravel)[akaunting/laravel-money

Currency formatting and conversion package for Laravel

7825.3M18](/packages/akaunting-laravel-money)[dragon-code/pretty-routes

Pretty Routes for Laravel

10058.7k4](/packages/dragon-code-pretty-routes)[pressbooks/pressbooks

Pressbooks is an open source book publishing tool built on a WordPress multisite platform. Pressbooks outputs books in multiple formats, including PDF, EPUB, web, and a variety of XML flavours, using a theming/templating system, driven by CSS.

44643.1k1](/packages/pressbooks-pressbooks)[flarum/core

Delightfully simple forum software.

211.3M1.9k](/packages/flarum-core)[bjuppa/laravel-blog

Add blog functionality to your Laravel project

483.3k2](/packages/bjuppa-laravel-blog)

PHPackages © 2026

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