Integrating 1C-Bitrix with Mailchimp

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1175
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    747
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

1C-Bitrix Integration with Mailchimp

Mailchimp is the most widely used Western ESP, featuring a powerful API and mature automation tools. For Russian-language projects, its use is justified when working with an international audience or when the client already runs their marketing through Mailchimp.

Mailchimp API v3

Mailchimp provides REST API v3. The base URL depends on the account's data center: https://us1.api.mailchimp.com/3.0/ (replace us1 with your account's data center — it is shown in the URL after login).

Authentication uses Basic Auth: any string as the username, API key as the password (from Account → API Keys).

Adding a subscriber to an Audience (list)

class MailchimpClient {
    private string $apiKey;
    private string $dataCenter;
    private string $listId;

    public function __construct() {
        $this->apiKey     = COption::GetOptionString('site', 'mailchimp_api_key');
        $this->dataCenter = explode('-', $this->apiKey)[1]; // us1, us2, etc.
        $this->listId     = COption::GetOptionString('site', 'mailchimp_list_id');
    }

    public function upsertMember(string $email, array $mergeFields = [], array $tags = []): array {
        $subscriberHash = md5(strtolower($email));
        $url = "https://{$this->dataCenter}.api.mailchimp.com/3.0/lists/{$this->listId}/members/{$subscriberHash}";

        $http = new \Bitrix\Main\Web\HttpClient();
        $http->setHeader('Authorization', 'Basic ' . base64_encode('anystring:' . $this->apiKey));
        $http->setHeader('Content-Type', 'application/json');

        $data = [
            'email_address' => $email,
            'status_if_new' => 'subscribed', // do not overwrite the status of unsubscribed members
            'merge_fields'  => $mergeFields, // FNAME, LNAME, PHONE, CITY, etc.
            'tags'          => $tags,
        ];

        // PUT — creates or updates (upsert)
        $response = $http->query(HttpClient::HTTP_PUT, $url, json_encode($data));
        return json_decode($response, true);
    }
}

The PUT /members/{hash} method acts as an upsert — it creates a new subscriber or updates an existing one by the email hash. This prevents duplicates.

Merge fields and tags

Merge fields — custom audience fields in Mailchimp. Standard fields: FNAME, LNAME. Create additional ones in the audience settings:

Merge tag Type Source in Bitrix
FNAME Text USER.NAME
LNAME Text USER.LAST_NAME
PHONE Phone USER.PERSONAL_PHONE
CITY Text Profile property
ORDERS Number Order count
LTV Number Total order value

Tags — free labels for segmentation. Synchronized with Bitrix user groups (b_user_group):

// Get Mailchimp tags for a user
function getUserMailchimpTags(int $userId): array {
    $tags = [];
    $groups = CUser::GetUserGroup($userId);
    $tagMap = ['9' => 'buyer', '12' => 'vip', '15' => 'wholesale'];
    foreach ($groups as $groupId) {
        if (isset($tagMap[$groupId])) $tags[] = $tagMap[$groupId];
    }
    return $tags;
}

Case: abandoned cart

Situation. An electronics e-commerce store with a 18% cart conversion rate. Goal: automatically send an email with the cart contents 1 hour after items are added, if the order has not been placed.

Implementation. Bitrix stores carts of unregistered users in b_sale_basket. On cart save (OnSaleBasketSaved), schedule an agent for 1 hour later:

AddEventHandler('sale', 'OnSaleBasketSaved', function($basket) {
    $userId = $basket->getFUserId();
    // Agent will check in one hour — if no order was placed, push to Mailchimp
    CAgent::AddAgent(
        'AbandonedCartAgent::check(' . $userId . ');',
        'my_module', 'N', 3600 // after 3600 seconds
    );
});

The agent checks: if no order was created, it passes the cart data to Mailchimp via POST /lists/{id}/members/{hash}/events — the abandoned_cart event triggers the automation in Mailchimp.

Handling the unsubscribe webhook

Mailchimp sends a POST to the configured URL on unsubscribe or bounce:

// /bitrix/tools/mailchimp_webhook.php
$data = $_POST;
if ($data['type'] === 'unsubscribe') {
    $email = $data['data']['email'];
    // Update status in Bitrix
    $mailchimp->updateLocalSubscription($email, 'unsubscribed');
}
if ($data['type'] === 'cleaned') {
    // Hard bounce — address is invalid
    $mailchimp->markEmailInvalid($data['data']['email']);
}
Task Effort
API client + basic synchronization 4–6 h
Merge fields + tags by group 3–4 h
Abandoned cart automation 6–8 h
Unsubscribe and bounce webhooks 3–4 h