Issue #3471021 by renrhaf: Add Brevo newsletter subscription webform handler.
Closes #3471021. Integrates a Brevo newsletter subscription webform handler directly into the Brevo module, per the "join forces" discussion in #3553922.
What it does
Adds a Brevo newsletter subscription webform handler (brevo_contact). On submission it subscribes the submitter to one or more Brevo contact lists through the shared ContactsApiClientHelper from the main module — so the API key configured for Brevo is reused, no separate credentials.
Configuration
- Email element — which webform element holds the email.
- Brevo lists — one or more lists, fetched live from the API.
- Opt-in checkbox element (optional) — only subscribe when a chosen checkbox is ticked; leave empty to always subscribe.
- Attribute mapping (optional) — JSON mapping Brevo attribute names to webform element keys, e.g.
{"FNAME": "first_name"}. - Double opt-in (optional) — send a Brevo DOI confirmation email (template ID + redirect URL) instead of subscribing directly.
Why in the main module (not a separate module)
Per #3553922, the Brevo module is the natural base holding API credentials and the base Contacts API methods; handlers build on it. Placing this next to the existing Brevo Transactional Email handler means shared credentials and a single place to maintain — what the brevo_webform_handler maintainers asked for. Webform remains an optional dependency: the handler is only discovered when Webform is installed.
Tests
BrevoContactHandlerTest (kernel) covers: basic subscription + attribute mapping, opt-in gating (ticked/unticked), missing email, and double opt-in. Config schema for the handler is included (validated by the generic module test).
Validation
Validated locally on Drupal 11.3 / PHP 8.3: PHPCS (Drupal, DrupalPractice) and PHPStan clean on the new code; a live drush runtime smoke test confirmed the handler is discovered, attaches to a webform, respects the opt-in checkbox, and routes a submission through to ContactsApiClientHelper::createContact().
Credit to the brevo_webform_handler authors (@Anybody, @StijnStroobants, @anruether, @kensae) whose module and discussion inspired this integration.