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

Core Lib Laravel Package

mautic/core-lib

Core library for Mautic, the open-source marketing automation platform. Provides shared PHP classes, services, and utilities used across Mautic bundles, helping developers build and extend campaigns, contacts, segments, and integrations.

View on GitHub
Deep Wiki
Context7

Getting Started

mautic/core-lib is not a Laravel package you install with composer require. It is the shared PHP foundation (entities, repositories, services, config) of Mautic's marketing-automation platform — a standalone Symfony 4.4 / PHP 7.4–8.0 application with its own database, container, and cron suite. Read the repo to understand the domain model and API contract; you will never boot it inside a Laravel process.

Day to day you will be integrating with a running Mautic instance over its REST API and webhooks. Start there, not with the source tree.

Minimal steps

  1. Provision Mautic (Docker Compose is fastest) and confirm /api/ responds. Open the Swagger UI that ships at https://your-mautic/api/ — that is the real reference for what you will call.
  2. Pick auth. For server-to-server Laravel integration, Basic auth is the pragmatic default: set 'api_enable_basic_auth' => true in config/local.php and provision a dedicated API user. OAuth2 is only worth the refresh-token machinery if you need per-user scoping or delegated third-party access.
  3. Add the official SDK — it is plain PHP and drops into Laravel cleanly:
    composer require mautic/api-library
    
  4. Bind it once in a service provider instead of constructing clients per call:
    // App\Providers\MauticServiceProvider
    $this->app->singleton('mautic.contacts', function ($app) {
        $auth = (new \Mautic\Auth\ApiAuth())->newAuth('BasicAuth', [
            'userName' => config('services.mautic.user'),
            'password' => config('services.mautic.password'),
        ]);
    
        return (new \Mautic\MauticApi())->newApi(
            'contacts', $auth, rtrim(config('services.mautic.base_url'), '/')
        );
    });
    
  5. Wrap it behind a MauticClient interface so tests and future Mautic 5 upgrades do not touch call sites.

First use case to validate end-to-end: take a Laravel registration, create the contact in Mautic, add them to a segment, and confirm the segment triggers a campaign. That single path exercises auth, field aliases, the contacts and segments endpoints, and Mautic's cron workers — the four things that break first.

Implementation Patterns

Never call Mautic in the request cycle. Every write belongs in a queued job. The API is slow, non-transactional with your DB, and a Mautic outage must not take down signup or checkout.

SyncContactToMautic::dispatch($user)->onQueue('marketing');

Upsert, don't create. Mautic dedupes on email but returns a 400 on genuine conflicts. Look up first, then edit or create:

$existing = $contactsApi->getList("email:{$user->email}", 0, 1, 'id', 'ASC');

$payload = [
    'email'     => $user->email,
    'firstname' => $user->first_name,
    'lastname'  => $user->last_name,
    'ipAddress' => $user->registration_ip,
    'tags'      => ['laravel', 'plan:'.$user->plan],
];

$contact = empty($existing['contacts'])
    ? $contactsApi->create($payload)
    : $contactsApi->edit($existing['contacts'][0]['id'], $payload, true); // true = PATCH

The third argument (true) is what developers miss most — without it edit() sends a PUT and blanks every field you don't include.

Batch aggressively for backfills and importers. Use createBatch() / editBatch() in chunks of 100 (Mautic's hard cap):

$users->chunk(100)->each(fn ($chunk) =>
    $contactsApi->createBatch($chunk->map(fn ($u) => [...])->all())
);

Segments are the integration point, not tags. Tags are fine for ad-hoc filtering, but campaigns fire off segment membership. Use addContact() / removeContact() and let mautic:segments:update do the evaluation — never assume membership is queryable immediately after the call returns.

Webhook receiver that actually works. Mautic posts application/x-www-form-urlencoded, not JSON:

Route::post('/webhooks/mautic/{secret}', MauticWebhookController::class)
    ->withoutMiddleware([\App\Http\Middleware\VerifyCsrfToken::class]);

Check the {secret} path segment against config, then hand the raw input to a job keyed on eventId for idempotency. Do not try to validate() the payload shape — keys vary per trigger type.

Define field aliases before you push them. Mautic will not auto-create custom fields from an API payload. Create them once via /api/fields/contact/new, cache the alias map in config, then push. Sending 'plan' => 'pro' with no plan alias means the value silently disappears.

Identity mapping. Add mautic_contact_id to your local model, backfill it via a job, and keep a reconciliation job looking for form-created contacts that never mapped back.

Client-side tracking. Drop mtc.js into the base Blade layout and use mt('send', 'pageview', {...}) for anonymous identification; reserve the API for anything that must be authoritative. Don't double-count the same event through both paths.

Gotchas and Tips

  • /api/leads is /api/contacts. The legacy naming lives throughout the API and SDK — getContacts() returns lead-shaped data. Read docs with that translation in your head.
  • Pagination is offset-based, not Laravel's paginator. $start + $limit, limit capped at 100. There is no total you can trust under concurrent writes — loop until an empty page, never on a count.
  • Search is its own DSL. getList('email:[email protected]') handles the shorthand; complex queries need the where[n][col|expr|val] array form. Escape !, %, and : in user-supplied values, or you get silent zero-result queries instead of errors.
  • Error handling is coarse. Reach into ApiException::getResponse()->getBody() for the real validation message; getCode() gives you 400 vs 401 vs 404. A 404 frequently means "endpoint not enabled for this user's role," not "resource missing."
  • Cron is the app. If mautic:segments:update, mautic:campaigns:update, and the email queue commands are not running, segments and campaigns go stale silently and emails never send. Alert on a cron heartbeat, not on error logs.
  • OAuth token expiry looks like an outage. Broad 401s are almost always expired credentials or a misconfigured client, not a down instance. Refresh proactively; wrap calls in retry with backoff.
  • Webhook retries cause duplicates. Mautic retries on non-2xx. Consumers must be idempotent and keyed on event ID.
  • 4.4.x is legacy. PHP 7.4/8.0 and Symfony 4.4 — plan against Mautic 5 before your platform baseline forces it. The 4.4.1 patch release itself is low-risk (bug fixes only, standard composer update + doctrine:migrations:migrate + cache clear on the Mautic host).
  • You own the client. No Laravel-native wrapper exists with meaningful traction — budget time to build and maintain MauticClient yourself, with a circuit breaker so Mautic slowness cannot cascade into user-facing latency.
  • PII blast radius. Contact and engagement data lands in a second datastore. Isolate its DB, restrict egress, and make sure GDPR erasure and retention flows cover both systems before going live.
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.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo