Skip to main content

Sync email opt-outs to Mailchimp

Premium Beginner

When a listener opts out of Benecaster emails, mirror it onto their Mailchimp contact so the preference is the same in both places, and flip them back when they opt in again from an email’s Resubscribe button or the account page’s Email preferences. With Email Editor active, broadcast sends also respect the opt-out automatically.

Mirror only the levels that mean “no marketing email”: broadcast and all. Both hooks fire once for each level a listener changes, so a listener who turns off only new-episode emails (episode_notifications) must not be dropped from your whole list.

Code

<?php
const MY_MIRRORED_LEVELS = [ 'broadcast', 'all' ];

add_action( 'benecaster_email_unsubscribed', function ( ?int $user_id, int $show_id, string $type ): void {
    // $user_id is null for a one-click unsubscribe by someone not logged in.
    if ( null === $user_id || ! in_array( $type, MY_MIRRORED_LEVELS, true ) ) {
        return;
    }
    my_mailchimp_update_status( $user_id, 'unsubscribed' );
}, 10, 3 );

add_action( 'benecaster_email_resubscribed', function ( ?int $user_id, int $show_id, string $type ): void {
    if ( null === $user_id || ! in_array( $type, MY_MIRRORED_LEVELS, true ) ) {
        return;
    }
    // A listener opted out at both levels who clears one is still opted out at the other.
    // If that matters for your list, track both levels from these two hooks first.
    my_mailchimp_update_status( $user_id, 'subscribed' );
}, 10, 3 );

function my_mailchimp_update_status( int $user_id, string $status ): void {
    $user = get_userdata( $user_id );
    if ( ! $user instanceof WP_User ) {
        return;
    }
    $hash = md5( strtolower( $user->user_email ) );
    wp_remote_request( 'https://us1.api.mailchimp.com/3.0/lists/YOUR_LIST/members/' . $hash, [
        'method'   => 'PATCH',
        'timeout'  => 5,
        'blocking' => false,
        'headers'  => [
            'Authorization' => 'Basic ' . base64_encode( 'anystring:' . MY_MAILCHIMP_API_KEY ),
            'Content-Type'  => 'application/json',
        ],
        'body'     => wp_json_encode( [ 'status' => $status ] ),
    ] );
}

View on GitHub →

Hooks Used

Need this built rather than just documented? See our services →