piwik/referrer-spam-blacklist
A Composer package providing a regularly updated list of referrer spam domains in plain text, plus a small PHP builder that converts it to JSON. Use it to filter fake traffic in analytics, block spam referrers, or feed your own blacklist.
Architecture fit
composer require.Integration feasibility
vendor/piwik/referrer-spam-blacklist/referrer-spam-blacklist.txt. Read once, normalize (lowercase, strip port, strip www., handle IDN/punycode), array_flip() into a hash set, then O(1) lookup against parse_url($request->headers->get('referer'), PHP_URL_HOST).Technical risk
Referer header is attacker-controlled and frequently absent (privacy browsers, Referrer-Policy: no-referrer, stripped cross-origin requests, corporate proxies). Any actor who reads the list can omit or spoof past it. This package catches lazy, opportunistic, off-the-shelf bots — it does not stop a motivated actor, and it must never be positioned internally as "we solved form spam."composer update silently changes production filtering behavior. That is a governance gap most teams do not have a control for.Key questions
Referrer-Policy and do we rely on referrer data anywhere legitimate (attribution, partner settlement, affiliate tracking)?Stack fit
spam_referrer flag on the entity, or reject with a cheap 404. Storing a flag rather than dropping the record preserves the ability to audit and to reverse a bad decision.config/spam-referrer.php) with enabled, mode (log|flag|block), allow_list, and cache TTL.spam:referrers:compile) producing a versioned cache key, run as a deploy step.Migration path
Compatibility
vendor/ is pruned before deploy (compile the cache artifact before the prune step).Sequencing
log mode, no enforcement. Success criterion: we can state spam-referrer hit rate per endpoint and confirm zero legitimate traffic matches.Each step should be independently revertible via a config flag. Do not ship 1–3 in one PR.
Maintenance
composer update is an unreviewed production filtering change. This is cheap (a line count and a sample of new hosts) and is the entire governance control.Support
Scaling
file_get_contents + parse variant costs disk/network I/O and milliseconds on every request, multiplied across the fleet.Failure modes
| Failure | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Cache cold/missing in a new pod | Medium | Per-request file parse, latency spike | Fail-open to "no match"; warm at deploy; alert on cold-cache reads |
| Bad hostname added upstream, hard-enforced | Medium | Real user/partner blocked | Log-only rollout, allow-list wins, per-decision logs |
| Upstream repo archived / releases stop | Low–Medium | List goes stale, silent decay | Fork + self-publish fallback; monitor last-release age |
| Malformed/oversized list line breaks parser | Low | Missed matches or parse error | Defensive parsing, fixture tests, skip-on-error |
| Long-lived Octane worker holds stale set | Medium | Inconsistent decisions across workers | Versioned cache key, not static memoization |
| Team treats this as complete anti-spam | High | Underinvestment, abuse escalation | Explicit "baseline, not strategy" statement in the design doc |
The most probable real-world failure is not technical — it is organizational: the blocklist gets adopted, works well enough against junk traffic, and quietly becomes the only abuse control, deferring a WAF/bot-management decision until abuse volume has already cost something. Name the escalation trigger up front (e.g., spam submissions exceed N/week or show adaptation) so the deferral is a tracked decision rather than a default.
Ramp-up
How can I help you explore Laravel packages today?