{"id":51914401,"url":"https://github.com/whilesmartphp/eloquent-campaigns","last_synced_at":"2026-07-27T09:30:28.989Z","repository":{"id":372636283,"uuid":"1282353211","full_name":"whilesmartphp/eloquent-campaigns","owner":"whilesmartphp","description":"Channel-agnostic campaign attribution for Laravel: owner-scoped campaigns, source-tagged events and conversions, per-source analytics.","archived":false,"fork":false,"pushed_at":"2026-07-22T14:45:40.000Z","size":24,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"dev","last_synced_at":"2026-07-22T15:16:16.193Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/whilesmartphp.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-27T16:53:48.000Z","updated_at":"2026-07-22T13:16:36.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/whilesmartphp/eloquent-campaigns","commit_stats":null,"previous_names":["whilesmartphp/eloquent-campaigns"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/whilesmartphp/eloquent-campaigns","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/whilesmartphp%2Feloquent-campaigns","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/whilesmartphp%2Feloquent-campaigns/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/whilesmartphp%2Feloquent-campaigns/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/whilesmartphp%2Feloquent-campaigns/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/whilesmartphp","download_url":"https://codeload.github.com/whilesmartphp/eloquent-campaigns/tar.gz/refs/heads/dev","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/whilesmartphp%2Feloquent-campaigns/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35947060,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"online","status_checked_at":"2026-07-27T02:00:06.776Z","response_time":101,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-27T09:30:28.321Z","updated_at":"2026-07-27T09:30:28.982Z","avatar_url":"https://github.com/whilesmartphp.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# whilesmart/eloquent-campaigns\n\nChannel-agnostic campaign attribution for Laravel. Group activity into owner-scoped **campaigns**, record **source-tagged events** (a creator's link click, an email open, an ad impression, a signup, a purchase), and report **per-source performance** including conversions and value.\n\nA campaign is just a named, owner-scoped initiative. What feeds it is up to the host, so the same package powers:\n\n- tracking which **creators** convert from their links,\n- a **marketing campaign** on a business dashboard,\n- an **email re-engagement** blast to inactive users.\n\nEach campaign is scoped to an owner (workspace, organization, team, user) through [`whilesmart/eloquent-owner-access`](https://github.com/whilesmartphp/eloquent-owner-access).\n\n## Install\n\n```\ncomposer require whilesmart/eloquent-campaigns\nphp artisan migrate\n```\n\nRoutes register automatically under the `api` prefix with `auth:sanctum`. Set `CAMPAIGNS_REGISTER_ROUTES=false` to mount them yourself. Bind your own `OwnerAuthorizer` to enforce who can see which owner's campaigns (the default allows all authenticated requests).\n\n## Owning model\n\n```php\nuse Whilesmart\\Campaigns\\Traits\\HasCampaigns;\n\nclass Workspace extends Model\n{\n    use HasCampaigns;\n}\n\n$campaign = $workspace-\u003ecampaigns()-\u003ecreate(['name' =\u003e 'Summer Creator Push']);\n```\n\n## Record events from any channel\n\n```php\n// A creator's link click (web)\n$campaign-\u003erecordEvent('click', [\n    'source' =\u003e 'jane_creator',\n    'visitor_hash' =\u003e $signature,\n    'subject' =\u003e $link,\n    'metadata' =\u003e ['device' =\u003e 'mobile', 'country' =\u003e 'US'],\n]);\n\n// A conversion ($ value attributed back to the source that drove it)\n$campaign-\u003erecordEvent('conversion', ['source' =\u003e 'jane_creator', 'value' =\u003e 49.99]);\n\n// An email open / signup (no clicks at all)\n$campaign-\u003erecordEvent('open', ['source' =\u003e 'inactive_30d']);\n$campaign-\u003erecordEvent('signup', ['source' =\u003e 'inactive_30d']); // counts as a conversion\n```\n\n`type` is a plain string, so any channel can define its own events. Which types count as conversions is configurable (`conversion_types`).\n\n`visitor_hash` is an **opaque unique-actor id you supply** (a hashed IP+UA for web traffic, a recipient id for email, a device id for push). The package never computes it, so it makes no assumption about the channel; it only uses it for unique counts and to match a conversion back to the actor's earlier event.\n\n## Endpoints\n\n| Method | Path | Purpose |\n|--------|------|---------|\n| GET | `/api/campaigns` | List (filter by `is_active`, `q`, owner) |\n| POST | `/api/campaigns` | Create |\n| GET | `/api/campaigns/{campaign}` | Show |\n| PUT/PATCH | `/api/campaigns/{campaign}` | Update |\n| DELETE | `/api/campaigns/{campaign}` | Soft delete |\n| GET | `/api/campaigns/{campaign}/analytics` | Per-source attribution report (`?from`, `?to`) |\n| POST | `/api/campaigns/{campaign}/events` | Record an event |\n\n## Analytics shape\n\n```json\n{\n  \"total_events\": 4, \"engagements\": 3, \"unique_visitors\": 3,\n  \"total_conversions\": 1, \"conversion_rate\": 33.3, \"total_value\": 49.99,\n  \"by_source\": [\n    { \"source\": \"jane\", \"events\": 3, \"engagements\": 2, \"visitors\": 2, \"conversions\": 1, \"value\": 49.99, \"conversion_rate\": 50 }\n  ],\n  \"by_type\": [{ \"type\": \"click\", \"count\": 3 }],\n  \"by_day\": [{ \"date\": \"2026-06-27\", \"count\": 4 }]\n}\n```\n\n## License\n\nMIT © WhileSmart LTD\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwhilesmartphp%2Feloquent-campaigns","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwhilesmartphp%2Feloquent-campaigns","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwhilesmartphp%2Feloquent-campaigns/lists"}