Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Mailchimp Laravel Package

splash/mailchimp

A Laravel package for integrating Mailchimp with your application, providing a simple way to connect to the Mailchimp API and manage lists, subscribers, and campaigns from your PHP code.

View on GitHub
Deep Wiki
Context7

Getting Started

Start by confirming the package actually installs in your target Laravel version before writing any code around it. splash/mailchimp is part of the Splash connectors family, which predates and sits outside the Laravel ecosystem proper — it is a Symfony-style bundle (MailChimpBundle) exposing a service definition plus a thin connector that wraps an embedded MailChimp client library (the "Embedded" suffix means the HTTP client is vendored in rather than pulled as a hard dependency). With zero stars and zero dependents, treat it as unvetted third-party code: audit composer.json, the Resources/config/services.* file, and the connector class before adopting it.

Minimal steps:

composer require splash/mailchimp
  1. Look first at the bundle's Resources/config/ directory — this is where the service ID, API key parameter, and default list ID are declared. That file tells you more about intended usage than any README will.
  2. Identify the connector service ID and the underlying embedded client class. The connector is almost certainly a thin façade: subscribe($listId, $email, $mergeVars), unsubscribe(...), getLists(), getMembers(...).
  3. If you are on Laravel, register the bundle's service definitions manually in a MailChimpServiceProvider (Laravel's container won't auto-discover a Splash bundle). Bind a singleton that receives your API key from config('services.mailchimp.key').

First use case — and the one that justifies the package at all — is a newsletter signup endpoint: POST /newsletter → validate the email → dispatch a queued job → subscribe(config('services.mailchimp.list_id'), $email, ['FNAME' => $name]). If that flow cannot be made to work cleanly in an hour, stop; the package is not saving you anything over drewm/mailchimp-api or Laravel's own Http facade against API v3.

Implementation Patterns

Wrap, never inject directly. The connector is the only surface you should touch, and it should be bound behind your own interface (NewsletterSubscriber). That single indirection makes the package swappable and lets you mock it in tests without depending on Splash's container semantics.

$this->app->singleton(NewsletterSubscriber::class, fn ($app) => new MailChimpSubscriber(
    $app->make('splash.mailchimp.connector'),
    config('services.mailchimp.list_id'),
));

Configuration and credentials. Move everything the bundle declares as a parameter into config/services.php:

'mailchimp' => [
    'key'     => env('MAILCHIMP_KEY'),
    'list_id' => env('MAILCHIMP_LIST_ID'),
],

Bind these into the connector at container resolution time. Never let the bundle read parameters straight out of parameters.yml-style config — in Laravel that convention doesn't exist and you'll end up hardcoding.

Queue every write. Subscribes and unsubscribes are network calls to a service that rate-limits you, so they belong in ShouldQueue jobs with $tries = 3 and an exponential backoff ([10, 60, 300]). This also decouples a MailChimp outage from your signup form's response time.

Treat subscribe as idempotent. The most common day-to-day pattern is "user does X, ensure they're on list Y." Model it as an upsert: attempt the subscribe, catch the "already exists" error, and treat it as success rather than branching on a prior lookup. This halves your API calls and removes a race condition.

Batch flows. For imports or resyncs, chunk your users (500 per batch is a safe ceiling against MailChimp's batch endpoint limits) and log per-item results rather than failing the whole chunk. Record the MailChimp email_address and the resulting status so you can reconcile later.

Test at the seam. Because the embedded client likely does not use Guzzle in a way that plays nicely with Http::fake(), bind a fake NewsletterSubscriber in feature tests and unit-test your own adapter against a stubbed connector. Do not try to intercept the embedded client's transport.

Gotchas and Tips

  • Maintenance risk is the headline. Zero stars, zero dependents, hosted on GitLab under a connectors org — assume no security patches and no compatibility work for new PHP or Symfony versions. Pin the exact version, and be prepared to fork it into your own namespace the first time a dependency conflict appears.
  • API version drift. "Embedded" connectors frequently bundle MailChimp API v2-era clients or an old drewm/mailchimp-api copy. v2 is long dead. Check whether the embedded client targets /3.0/ paths; if it doesn't, this package is a liability and you should call API v3 directly.
  • Dependency conflicts. The embedded client likely pins an old Guzzle (^5 or ^6). Modern Laravel ships Guzzle 7 — expect a Composer resolution fight. Isolate in a separate package/service if you cannot resolve it.
  • API key format. MailChimp keys carry their datacenter suffix (abc123-us14). The client derives the base URL from that suffix. If you see 401s on every call, verify the suffix survived your .env and wasn't truncated by a # or quote mishandling.
  • "Already subscribed" is not an error. MailChimp returns HTTP 400 with title: "Member Exists". Catching and swallowing this is correct; surfacing it to the user is not.
  • Status semantics. subscribed, pending (double opt-in), unsubscribed, cleaned, archived are distinct. A signup flow that expects subscribed will silently mis-report if the list is set to double opt-in. Read the returned status rather than assuming.
  • Rate limits. ~10 concurrent connections and a rolling request budget. If your queue workers spin up wide, add a rate limiter or throttle the queue; otherwise you'll collect 429s and retry storms.
  • Merge fields must pre-exist. Sending FNAME to a list without that merge tag configured throws a 400 that reads unrelated to the cause. Validate your merge var keys against getLists() output once, in a test.
  • Extension points are your escape hatch. If the connector class isn't final, subclass it and override the transport or add a retry() decorator. If it is final, decorate the connector behind your own interface from day one — that decision is cheap upfront and expensive later.
  • Debugging tip. Because the embedded client hides its HTTP layer, log the raw response body at your adapter boundary. When something fails you'll have no stack trace pointing into the vendored client, and the response body is usually the only artifact that explains a 400.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings