Skip to content

Newsletter Integrations (Mailchimp, Manago, Moosend, Apifon) ​

Flow ID: IN-13 | Module(s): ecommercen/libraries/, src/Manago/, src/Moosend/, src/Apifon/ | Complexity: High

Business Overview ​

Ecommercen integrates with four newsletter and marketing automation platforms to manage subscriber lists and track customer behavior. All integrations are triggered at two key customer touchpoints:

  1. Checkout -- Newsletter consent checkboxes during order completion subscribe or update the customer in the configured provider.
  2. Registration -- Account creation can automatically subscribe the customer.

Each provider has a distinct API style and feature set, but they share a common pattern: subscriber data is pushed from Ecommercen to the external platform (never pulled). The platform choice is per-client, configured via Registry settings.

ProviderAPI StyleKey Features
MailchimpREST (Marketing API v3)Two lists (site/checkout), interest groups, tags, double opt-in
ManagoREST (SHA-signed)Contact upsert with consent, purchase events, product recommendations
MoosendREST (API v3)Subscribe with custom fields, contact existence check
ApifonREST (OAuth2)SMS + Viber messaging, subscriber list management

API Reference ​

Mailchimp (Adv_Mailchimp_Api) ​

MethodDescription
getAllLists($count, $offset)Fetch all audience lists
addMemberToList($listId, $data)Subscribe a member to a list
getCategoriesAndGroups($listId)Fetch interest categories and groups for a list
getListTags($listId)Fetch tags for a list (includes custom site/checkout tags)
getAllListsWithGroupsAndInterests()Combined fetch: all lists with their groups, interests, and tags

Manago (Advisable\Manago\Manago) ​

MethodParametersDescription
contactExists($email)stringCheck if contact exists, returns contactId or null
saveContact($contact, $consentGiven, $visitorIp)array, bool, stringUpsert contact with consent details
addEvent($userId, $userOptChoice, $eventData)array, bool, arrayAdd purchase/behavior event to contact
getRecommendations($endpoint, $params)string, arrayFetch product recommendations for a contact
getMaxCostSeconds()--Returns max timeout for deferred task budget

Moosend (Advisable\Moosend\Moosend) ​

MethodParametersDescription
subscribe($listId, $subscribers)string, arraySubscribe contacts with custom fields
contactExists($listId, $email)string, stringCheck if contact exists in a list

Apifon (Advisable\Apifon\Apifon) -- Newsletter Features ​

MethodParametersDescription
subscribe($data)array (to, email, firstName, lastName)Add subscriber to configured list

Note: Apifon also handles SMS/Viber messaging -- see IN-14 SMS Integrations.

Code Flow ​

Mailchimp Subscription at Checkout ​

Customer completes checkout with newsletter checkbox checked
  -> Adv_checkout / Adv_order controller
     -> Load Mailchimp library (namespace: Mailchimp\Adv_Mailchimp_Api)
     -> initializeConfig():
        - API_KEY, SERVER_PREFIX from Registry (MAILCHIMP group)
        - SUBSCRIBE_AS_PENDING flag for double opt-in
        - Custom tag names for site vs checkout subscriptions
     -> addMemberToList($listId, [
          'email_address' => $email,
          'status' => $mailchimpSubscribeAsPending ? 'pending' : 'subscribed',
          'interests' => $interestId ? [$interestId => true] : (object)[],
          'tags' => $tagName ? [$tagName] : []
        ])
     -> MailchimpMarketing\ApiClient handles REST call to Mailchimp API v3

Manago Contact Sync ​

Customer registers or completes checkout
  -> Controller loads Manago via DI: di()->get(Manago::class)
  -> Manago::__construct(Registry, ?CircuitBreaker):
     - Builds SHA1 signature: sha1(API_KEY + CLIENT_ID + API_SECRET)
     - Sets requestTime = time() * 1000
  -> saveContact($contact, $consentGiven, $visitorIp):
     - POST to {API_BASE_URL}/contact/upsert
     - Includes: clientId, apiKey, sha, requestTime, owner, contact data
     - Consent details: consentName, agreementDate, ip, consentDescriptionId
     - Double opt-in: useApiDoubleOptIn = true
     - Consent flags: consentAccept/optOut based on $consentGiven
  -> On successful order, addEvent() tracks purchase:
     - POST to {API_BASE_URL}/v2/contact/addContactExtEvent
     - Includes: contactEvent data with order details
     - forceOptIn/forceOptOut based on customer preference

Manago Product Recommendations ​

Product page or recommendation widget
  -> Manago::getRecommendations($endpoint, $params)
     - POST to {API_BASE_URL}/recommendation/{endpoint}
     - Params include shopName from registry
     - Returns productIds array
     - Circuit breaker protected: skips call if circuit is open

Moosend Subscription ​

Customer action triggers subscribe
  -> Moosend::__construct(Registry):
     - API_KEY from Registry (MOOSEND group)
     - Guzzle client with 2-second timeout
  -> subscribe($listId, $subscribers):
     - POST to subscribers/{listId}/subscribe.json?apikey={key}
     - JSON body with subscriber data and custom fields
     - Returns bool based on Code === 0 and no Error

Apifon Subscriber Management ​

Customer opts in for notifications
  -> di()->get(Apifon::class)  (named 'apifon' logger injected; Registry resolved lazily at request time):
     - Reads APIFON.* registry keys (lazily, via the registry() helper)
     - OAuth2 authentication on first call
  -> subscribe($data):
     - Check: enabled, subscribeToListEnabled
     - authenticate(): POST to ids.apifon.com/oauth2/token (client_credentials)
     - getList(): GET list details, validate required fields (FIRST_NAME, LAST_NAME)
     - POST to /services/api/v1/list/{listId}/subscriber
     - Body: destination, status=SUBSCRIBED, email, email_status=SUBSCRIBED, subscriber_fields
     - HTTP 201 or 409 treated as success (409 = already exists)

Architecture ​

ecommercen/libraries/
  Adv_Mailchimp_Api.php          # Mailchimp Marketing API v3 wrapper

src/Manago/
  Manago.php                     # Manago REST API client with SHA-signed requests

src/Moosend/
  Moosend.php                    # Moosend API v3 REST client

src/Apifon/
  Apifon.php                     # Apifon OAuth2 + SMS/Viber/Subscriber API

ecommercen/feeds/controllers/
  AdvManagoXml.php               # Manago product feed (extends AdvGoogleCatalog)

application/modules/eshop/controllers/
  Mailchimp.php                  # Admin Mailchimp management controller

application/controllers/
  Manago.php                     # Client-level Manago controller

Dependencies ​

ClassExternal DependencyAuth Method
Adv_Mailchimp_Apimailchimp-marketing-php SDKAPI Key + Server Prefix
ManagoGuzzle HTTPSHA1(API_KEY + CLIENT_ID + API_SECRET) signature
MoosendGuzzle HTTPAPI Key in query string
ApifonGuzzle HTTPOAuth2 client_credentials + Bearer token

Fault Tolerance ​

  • Manago uses CircuitBreaker (optional). When circuit is open, API calls return empty results without making network requests. Success/failure is recorded after each call.
  • Moosend has a 2-second request timeout.
  • Apifon authenticates lazily (on first API call) and caches the access token for the request lifecycle.

Data Model ​

Manago Product Feed ​

The AdvManagoXml feed controller (extending AdvGoogleCatalog) exports products in Google Shopping XML format with Manago-specific ID prefixes (productIdToManagoId()). It includes a category field with the first parent category name.

Registry Keys Used ​

All provider settings are stored in the registry table and accessed via $this->registry->value('GROUP', 'KEY').

Configuration ​

Mailchimp (Registry) ​

GroupKeyDescription
MAILCHIMPENABLEDEnable/disable Mailchimp integration
MAILCHIMPAPI_KEYMarketing API key
MAILCHIMPSERVER_PREFIXAPI server prefix (e.g., us19)
MAILCHIMPSUBSCRIBE_AS_PENDINGDouble opt-in (pending) vs direct subscribe
MAILCHIMPCUSTOM_SITE_TAG_NAMETag name for site-originating subscriptions
MAILCHIMPCUSTOM_CHECKOUT_TAG_NAMETag name for checkout-originating subscriptions
MAILCHIMPSITE_TAGTag ID for site subscriptions
MAILCHIMPCHECKOUT_TAGTag ID for checkout subscriptions

Manago (Registry) ​

GroupKeyDescription
MANAGOAPI_KEYAPI authentication key
MANAGOCLIENT_IDClient identifier
MANAGOAPI_SECRETAPI secret for SHA signature
MANAGOAPI_BASE_URLAPI base URL
MANAGOUSER_ACCOUNT_EMAILOwner email for API requests
MANAGOCONSENT_NAMEGDPR consent name
MANAGOCONSENT_DESCRIPTION_IDConsent description identifier
MANAGOTIMEOUTRequest timeout in seconds
MANAGOSHOP_NAMEShop name for recommendations
MANAGODEBUG_CALLEnable request/response logging
MANAGOPRODUCT_ID_PREFIX_MANAGOProduct ID prefix for feed

Moosend (Registry) ​

GroupKeyDescription
MOOSENDAPI_KEYAPI authentication key

Apifon (Registry) ​

GroupKeyDescription
APIFONENABLEDEnable/disable Apifon integration
APIFONAPI_TOKENOAuth2 client_id
APIFONAPI_KEYOAuth2 client_secret
APIFONSENDER_IDSMS sender ID
APIFONTTLViber message TTL before SMS fallback
APIFONENABLE_IMEnable Viber instant messaging channel
APIFONSUBSCRIBE_TO_LIST_ENABLEDEnable subscriber list management
APIFONSUBSCRIBER_LIST_IDTarget subscriber list ID

Client Extension Points ​

Mailchimp ​

  • Override application/libraries/Mailchimp_Api.php to extend Adv_Mailchimp_Api with custom list logic.
  • Override application/modules/eshop/controllers/Mailchimp.php for admin panel customization.
  • Two-list pattern: Configure separate Mailchimp lists for site newsletter signups vs checkout signups, with different tags applied to each.

Manago ​

  • Override the DI container registration to inject custom CircuitBreaker configuration.
  • Override application/controllers/Manago.php for client-specific controller behavior.
  • The AdvManagoXml feed can be overridden via the standard feed extension pattern.
  • Product ID prefix (PRODUCT_ID_PREFIX_MANAGO) allows per-client ID namespacing.

Moosend ​

  • The Moosend class is instantiated directly (not via DI), so client overrides require controller-level changes.
  • Custom fields in the subscribe() payload are defined by the calling controller.

Apifon ​

  • All configuration is registry-based, making it fully configurable per client without code changes.
  • Subscriber list field validation (FIRST_NAME, LAST_NAME) is checked dynamically against the Apifon list schema.
  • Client-override seam (4.112.0, #387). Advisable\Apifon\Apifon is bound in src/Apifon/container.php and resolved everywhere via di()->get(Apifon::class). Six members are now protected (API_BASE_URL, LIST_ENDPOINT, $config, $logger, ensureAuthenticated(), getList()), so a client can subclass instead of editing upstream. Re-bind from custom/Apifon/container.php by registering Custom\Apifon\Apifon and aliasing it to Advisable\Apifon\Apifon::class; all call sites (sms_helper.php, Adv_order.php) pick up the subclass transparently.

Business Rules ​

  1. Double opt-in: Mailchimp supports SUBSCRIBE_AS_PENDING for GDPR-compliant double opt-in. When enabled, subscribers receive a confirmation email before being activated.
  2. Consent tracking: Manago records explicit consent details (consent name, agreement date, IP address) for GDPR compliance. The consentAccept/optOut flags are set based on the customer's explicit choice.
  3. Two-list Mailchimp pattern: Sites can maintain separate audiences for newsletter signups (site footer) and checkout signups, with different tags to distinguish origin.
  4. Manago SHA signature: Every API request is signed with SHA1(API_KEY + CLIENT_ID + API_SECRET) and timestamped. This prevents request tampering.
  5. Manago recommendations: Product recommendations from Manago are used alongside internal recommendation engines. The circuit breaker ensures that recommendation failures do not impact page load times.
  6. Moosend deduplication: The contactExists() check allows controllers to avoid duplicate subscription attempts.
  7. Apifon 409 handling: HTTP 409 (Conflict) responses from the subscriber endpoint are treated as success, indicating the subscriber already exists.
  8. Provider selection: The active newsletter provider is a per-client choice configured via Registry settings. Multiple providers can be active simultaneously (e.g., Mailchimp for email + Apifon for SMS/Viber).