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

Campaign Monitor Bundle Laravel Package

lukaszmordawski/campaign-monitor-bundle

Symfony bundle that integrates Campaign Monitor's email marketing API into your PHP application. Manage subscriber lists, campaigns, and transactional emails through configured services, with a lightweight wrapper that simplifies API setup and keeps email marketing operations accessible from your Sy...

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install (assuming a Symfony 2.x project):

    composer require lukaszmordawski/campaign-monitor-bundle
    
  2. Register the bundle in app/AppKernel.php:

    public function registerBundles()
    {
        $bundles = [
            // ...
            new LukaszMordawski\CampaignMonitorBundle\CampaignMonitorBundle(),
        ];
        return $bundles;
    }
    
  3. Configure credentials in app/config/config.yml (naming may vary slightly by version — check DependencyInjection/Configuration.php in the bundle source, which is the authoritative reference):

    campaign_monitor:
        api_key: "%campaign_monitor_api_key%"
    

    Keep the key in parameters.yml and never commit it.

  4. Look here first inside the bundle:

    • DependencyInjection/ — the extension and Configuration.php define the config tree and service wiring. This is your source of truth for service IDs and options.
    • Resources/config/services.xml (or .yml) — tells you exactly what service ID to fetch.
    • composer.json — shows the pinned Campaign Monitor SDK (campaignmonitor/createsend-php) version.
  5. First use case — fetch the client and pull a subscriber list:

    $client = $this->get('campaign_monitor')->getClient(); // adjust to actual service ID
    $lists  = $client->getLists();
    

    In a controller (Symfony 2 style) use $this->get('...'); in a service, inject the ID via services.yml.

Implementation Patterns

  • Thin service wrapper around the SDK. The bundle adds little beyond DI wiring; you should still wrap it in your own app-level service (App\Service\CampaignMonitorGateway) so controllers never touch Campaign Monitor objects directly. This makes the bundle swappable when it inevitably can't keep up with SDK/version changes.
  • Per-environment config. Point a dev/test API key at a sandbox Campaign Monitor account so you don't fire real campaigns or pollute live lists while iterating.
  • Console command for syncs. Campaign Monitor work is often long-running (importing subscribers, syncing lists). Put it in a Command and call the wrapper service rather than embedding it in a controller — this avoids request timeouts and lets you schedule via cron.
  • Async subscribers. Use the SDK's addSubscriber/importSubscribers batch methods where possible; wrap calls with a small queue entry (e.g., a Subscriber entity + Doctrine) so failed API calls can be retried.
  • Error handling at the boundary. The underlying SDK throws its own exception types (e.g., CurlException, BadRequestException). Catch them in your gateway and rethrow app-level exceptions so callers aren't coupled to the SDK.
  • Testing. Because the bundle is just a service factory, mock the Campaign Monitor SDK classes (or your wrapper) in unit tests. There's no test double provided by the bundle, so you supply your own stubs.
  • Extension point. If you need to pass SDK options (timeouts, proxies) not exposed via Configuration.php, override the service definition in your own services.yml (same ID, updated arguments) rather than editing vendor code.

Gotchas and Tips

  • Abandoned / Symfony 2-only. This was built for Symfony 2 and is not maintained (3 stars, 0 dependents). It almost certainly won't install cleanly on Symfony 3+ without patching the service definitions and namespace conventions. If you're on anything newer, skip the bundle and use campaignmonitor/createsend-php directly — the bundle adds little value beyond one service definition.
  • Service ID drift. The exact service ID and config keys aren't documented in the README; don't guess. Run php app/console debug:container campaign_monitor (Symfony 2.x) or grep services.xml to confirm the actual ID before wiring it up.
  • SDK version pinning. The bundle's composer.json pins an old SDK. If you need a newer API feature, you'll have to bump the SDK yourself and may hit breaking changes in class names/method signatures the bundle was written against.
  • API key leakage. config.yml gets committed; use parameters.yml + environment overrides. Also set campaign_monitor: ~ in config_test.yml so unit tests don't try to hit the network.
  • Debugging 401s. Most "it doesn't work" reports are a stale/whitespace-containing API key or the wrong account's key. Log the HTTP response body from the SDK exception — Campaign Monitor returns useful error messages there.
  • Rate limits. Campaign Monitor limits requests per time window. For bulk operations, throttle (e.g., usleep) or use the importSubscribers bulk endpoints; hammering the wrapper will get you 400s that surface as opaque SDK exceptions.
  • No extension points for retries. The bundle doesn't add retry logic — wrap calls in your gateway with a simple retry/backoff if reliability matters.
  • Container compilation. If you get "service not found" after install, check that AppKernel registration happened before the container is compiled and that you haven't disabled the extension via campaign_monitor: false.
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.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums