Aller au contenu
Patrick Junod Patrick Junod

Laravel: Abonner ses utilisateurs à une liste avec l'API Mailchimp

Ce tutoriel a été établi pour une installation Laravel 8 sur PHP 8 avec Livewire. Nous n'allons ici pas voir l'envoi des données de votre formulaire d'inscription à votre backend, mais nous concentrer sur la partie traitement de ces données.
Laravel MailChimp Programmation

1. Prérequis

Commençons premièrement par installer la dépendance de Spatie: Newsletter

composer require spatie/laravel-newsletter

Le paquet va automatiquement être découvert par Laravel.

Pour publier la configuration dans le dossier config/newsletter.php, faites simplement:

php artisan vendor:publish --provider="Spatie\Newsletter\NewsletterServiceProvider"

Ajoutez ensuite dans votre fichier .env les différentes variables requises par Spatie\Newsletter:

MAILCHIMP_DRIVER=api
MAILCHIMP_APIKEY=votre_api_key_mailchimp
MAILCHIMP_LIST_ID=votre_id_de_liste_mailchimp

2. Validation du formulaire

Validez vos données du formulaire. Voici pour l'exemple la validation de notre formulaire, contenant le prénom, le nom de famille, l'email et la validation que l'utilisateur souhaite recevoir la newsletter. Par soucis de lisibilité, nous avons supprimé certains champs supplémentaires (adresse, téléphone, etc..) :

app\Http\Livewire\Newsletter.php

return [
   'first_name' => 'required|string|max:255',
   'last_name' => 'required|string|max:255',
   'email' => 'required|email|max:255',
   'agreeNewsletter' => 'nullable|boolean',
// autres données pas affichées ici (adresse, téléphone, etc...)
];

Nous pouvons maintenant valider ces données (ici via Livewire) et y ajouter certaines métadonnées sur l'utilisateur (user agent, ip):

app\Http\Livewire\Newsletter.php

$data = $this->validate();

$userInfos = [
    'userAgent' => Request()->server('HTTP_USER_AGENT'),
    'ip' => Request()->ip(),
];

$data = array_merge($data, $userInfos);

Une fois le tableau de donnée prêt, nous pouvons attaquer l'envoi de la newsletter:

En premier lieu, nous validons bien que la personne a souhaité recevoir la newsletter via la boolean agreeNewsletter (ce formulaire d'exemple permet de s'inscrire à une liste d'attente et de recevoir la newsletter après Opt-In).

Puis, nous instancions une nouvelle action: SubscribeEmailToNewsletter avec les valeurs de notre formulaire. Nous allons le voir plus tard, mais les valeurs first_name, last_name et data ne sont ici pas obligatoires. L'email suffit pour une inscription à Mailchimp.

Et enfin, nous déclenchons l'envoi de la newsletter avec la méthode subscribe()

app\Http\Livewire\Newsletter.php

if($data['agreeNewsletter'] === true) {
    $newsletter = new SubscribeEmailToNewsletter($data['email'], $data['first_name'], $data['last_name'], $data);
    $newsletter->subscribe();
}

Profitons pour ajouter à notre Controller l'action que nous allons créer dans la prochaine étape:

app\Http\Livewire\Newsletter.php

use App\Actions\SubscribeEmailToNewsletter;

3. Création de l'action

Créez une nouvelle action (en savoir plus sur les actions - freek.dev - Anglais) qui sera déclenchée lorsque vous souhaitez abonner un nouvel utilisateur à votre liste Mailchimp. Pour cela, créez un nouveau dossier Actions dans votre dossier app.

Dans ce dossier, créez un fichier SubscribeEmailToNewsletter.php qui s'occupera de l'envoi des données à Mailchimp ainsi qu'à logger le résultat dans nos logs.

app\Actions\SubscribeEmailToNewsletter.php

<?php

namespace App\Actions;

use Newsletter;

class SubscribeEmailToNewsletter
{

    //

}

4. Construction de notre action

Nous allons commencer par définir notre constructeur. Pour cette classe, nous souhaitons pouvoir passer en tout cas une adresse email ($email), et si disponible un prénom ($fname) et un nom de famille ($lname). Nous voulons aussi avoir accès aux données de notre formulaire dans le cas où l'inscription ne s'est pas passée correctement et pour un debug simplifié (le tableau $data).

app\Actions\SubscribeEmailToNewsletter.php

<?php

namespace App\Actions;

use Newsletter;

class SubscribeEmailToNewsletter
{

    private $email;
    private $fname;
    private $lname;
    private $data;

    public function __construct(string $email, string $fname = null, string $lname = null, array $data = [])
    {
        $this->email = $email;
        $this->fname = $fname;
        $this->lname = $lname;
        $this->data = $data;
    }

}

5. Gestion de l'envoi de la demande d'inscription à Mailchimp

Attaquons-nous maintenant au coeur de notre classe: La préparation de la requête et l'envoi à Mailchimp. Grâce au paquet Spatie\Newsletter, cette étape se fait très facilement. Regardons premièrement la nouvelle méthode que nous venons d'ajouter: subscribe()

app\Actions\SubscribeEmailToNewsletter.php

<?php
/***
 * Handle the subscription of a user in Mailchimp
 */
public function subscribe()
{

// 1. Nous préparons le tableau des champs de fusion Mailchimp. 
// Si le prénom et/ou le nom sont fournis, 
// alors nous pouvons les intégrer à la requête.
    $merges = [];
    $this->fname ? $merges['FNAME'] = $this->fname : '';
    $this->fname ? $merges['LNAME'] = $this->lname : '';

// 2. Il est aussi possible d'ajouter une meta donnée à votre utilisateur
//  dans votre liste mailchimp si vous avez comme projet l'envoi de newsletters
//  dans plusieurs langues. Dans ce cas, ajouter l'option "language" et y passer
//  le code de langue souhaité. Ici, nous passerons simplement la langue actuelle de notre projet.
    $options = ['language' => app()->getLocale()];

// 3. Envoi de la demande d'inscription à Mailchimp. Nous utilisons ici l'option 
// "subscribeOrUpdate" permettant de mettre à jour l'utilisateur dans la liste 
// si il existe déjà, ou d'en créer un nouveau si non. Dans notre cas, le 
// troisième paramètre a été omis. Il est possible d'y intégrer le nom de la 
// liste que vous souhaitez utiliser si elle n'est pas celle par défaut définie dans votre fichier config newsletter.php
    $subscribed = Newsletter::subscribeOrUpdate($this->email, $merges, '', $options);

// 4. Nous allons voir cette ligne plus tard.
    $this->log($subscribed);
}

6. Loguer le résultat

Une fois l'action effectuée, il est toujours intéressant d'avoir un retour sur son résultat. Pour cela, nous pouvons intégrer une méthode permettant de loguer les informations sur l'utilisateur et le résultat de son inscription.

Ajoutez pour cela une méthode log() prenant en paramètre le résultat de l'inscription à la newsletter ($subscribed):

app\Actions\SubscribeEmailToNewsletter.php

/***
 * Log informations about the subscription
 * @param false $subscribed
 */
public function log($subscribed = false): void
{
    $subscribed
        ? Log::info('Newsletter subscription: ' . $this->email, ['data' => $this->data, 'subscribed' => $subscribed])
        : Log::error('Newsletter subscription failed for: ' . $this->email, ['data' => $this->data]);
}

Comme vous pouvez le voir, nous envoyons dans nos logs une information d'inscription réussie si celle-ci a bien été envoyée à Mailchimp, et une erreur si l'utilisateur n'a pas pu être rajouté. Simple et efficace. Dans notre exemple, nous intégrons aussi les données du formulaire utilisé pour l'envoi des données ($data) dans un soucis de debugging par la suite.

7. Résultat final

Voici le fichier SubscribeEmailToNewsletter.php finalisé:

app\Actions\SubscribeEmailToNewsletter.php

<?php

namespace App\Actions;

use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Newsletter;

class SubscribeEmailToNewsletter
{

    private $email;
    private $fname;
    private $lname;
    private $data;

    public function __construct(string $email, string $fname = null, string $lname = null, array $data = [])
    {
        $this->email = $email;
        $this->fname = $fname;
        $this->lname = $lname;
        $this->data = $data;
    }

    /***
     * Handle the subscription of a user in Mailchimp
     */
    public function subscribe()
    {

        $merges = [];
        $this->fname ? $merges['FNAME'] = $this->fname : '';
        $this->fname ? $merges['LNAME'] = $this->lname : '';

        $options = ['language' => app()->getLocale()];

        $subscribed = Newsletter::subscribeOrUpdate($this->email, $merges, '', $options);

        $this->log($subscribed);
    }

    /***
     * Log informations about the subscription
     * @param false $subscribed
     */
    public function log($subscribed = false): void
    {
        $subscribed
            ? Log::info('Newsletter subscription: ' . $this->email, ['data' => $this->data, 'subscribed' => $subscribed])
            : Log::error('Newsletter subscription failed for: ' . $this->email, ['data' => $this->data]);
    }
}