Études de cas
Comment la Launch School Academy a multiplié par 3 l’engagement des élèves
À la Tealeaf Academy, la création d’une expérience « Étudier ensemble, progresser ensemble » pour nos élèves est au cœur de notre méthode d’enseignement. L’un de nos outils principaux est le forum de discussion où les élèves posent des questions, partagent des idées, collaborent sur des devoirs, et où les professeurs interviennent rapidement pour aider les élèves à se débloquer sur des problèmes. L’une de nos récentes priorités était de réduire les frictions dans l’utilisation du forum de discussion et d’encourager davantage de discussions avec une notification par email complémentaire et un flux de travail « répondre à l’email pour publier sur le forum de discussion ».
Une fois que nous avons implémenté le code ci-dessous à l’aide de l’API Routes de Mailgun, l’activité sur notre forum de discussion a triplé, et les questions obtiennent désormais généralement une réponse en une heure, parfois même en quelques minutes, et les élèves sont capables de passer à la série de tâches suivante beaucoup plus rapidement. Voici comment nous avons procédé :
Notre flux de travail se présenterait comme suit :
- Lorsqu’une publication (très probablement, une question) est créée, tous les participants au cours sont informés par une notification par email
- Les participants au cours peuvent répondre aux notifications par email directement depuis leur boîte de réception d’emails, sans avoir à se connecter au cours
- Cette réponse sera publiée sur le forum de discussion en ligne et sera également envoyée aux autres participants au cours, afin de maintenir la conversation en cours.
Pourquoi nous choisissons Mailgun
L’élément clé de ce flux de travail est de recevoir et de parser les messages d’emails entrants. Nous avons examiné plusieurs services d’emailing, et avons finalement choisi Mailgun car :
- Il est très adapté aux développeurs – Nous sommes des développeurs, et Mailgun nous parle. Les API exposent de nombreuses options de bas niveau qui permettent des ajustements. Nous aimons les routes en particulier – C’est une belle couche d’abstraction qui rend l’intégration avec les applications très facile. (voyez comment nous l’utilisons ci-dessous)
- C’est le service le plus complet en fonctionnalités que nous ayons trouvé – nous pouvons utiliser Mailgun pour les emails transactionnels, les campagnes ainsi que les listes de contacts – c’est agréable de n’avoir qu’un seul fournisseur de services pour gérer tout ce dont nous avons besoin.
- Le prix est raisonnable et la possibilité de mettre à niveau vers une adresse IP dédiée et un DKIM personnalisé est appréciable, même si nous n’en avons pas encore besoin.
- Le support est de premier ordre. Il y a un chat en direct où je peux parler directement de mes problèmes à leurs développeurs et il nous a été très utile pour les résoudre.
Mise en place de l’infrastructure d’email
- La première étape a été de créer un nouveau domaine sur Mailgun. Dans notre cas, il s’agit de messaging.gotealeaf.com que nous utilisons pour l’envoi et la réception d’emails.
- Ensuite, nous avons créé un MailgunGateway comme wrapper pour l’API de Mailgun. Ce wrapper prend en charge toutes nos interactions avec Mailgun via notre compte. Ici, nous utilisons l’API send_batch_messages de Mailgun pour envoyer des emails HTML. Elle nous permet d’envoyer un message à plusieurs destinataires avec un appel d’API unique. Nous conservons notre clé API en tant que variables d’environnement sur le serveur pour plus de sécurité. Il existe également un filtre de livraison simple pour qu’aucun email ne soit envoyé dans l’environnement de développement ; Sur l’environnement de staging, tous les emails sont envoyés à Chris (mon co-fondateur) et à moi-même, ce qui nous permet de tester des choses sans craindre d’envoyer du spam à nos utilisateurs ; Ce n’est que sur l’environnement de production que les emails sont envoyés aux utilisateurs réels.
class MailgunGateway
def send_batch_message(options={})
RestClient.post(messaging_api_end_point,
from: default_sender,
to: delivery_filter(options[:to]),
subject: options[:subject],
html: options[:body],
:"h:Reply-To" => options[:reply_to],
:"recipient-variables" => options[:recipient_variables]
) if Rails.env.staging? || Rails.env.production?
end
end
private
def default_sender
"Tealeaf Academy "
end
def api_key
@api_key ||= ENV['mailgun_api_key']
end
def messaging_api_end_point
@messaging_api_end_piont ||=
"https://api:#{api_key}@api.mailgun.net/v2/messaging.gotealeaf.com/messages"
end
def delivery_filter(emails)
Rails.env.production? ? emails : "kevin@gotealeaf.com, chris@gotealeaf.com"
end
end
Envoyer des notifications par email pour un nouveau post ou commentaire
Une fois qu’un post ou un commentaire est créé, nous envoyons une notification par email à tous les participants du cours. Nous envoyons des emails de manière synchrone pour le moment, mais à mesure que nous aurons plus d’utilisateurs, nous voudrons probablement déléguer cela à une tâche d’arrière-plan.
Launch School Code 1class Courses::PostsController < AuthenticatedController
expose(:course)
expose(:posts) { course.posts }
expose(:post)
def create
post.user = current_user
post.save
CourseNotifier.new(course).notify_course_participants_on_new_discussion(post)
redirect_to course_home_path(course)
end
...
end
class Courses::Posts::CommentsController < AuthenticatedController
expose(:course)
expose(:posts) { course.posts }
expose(:post)
expose(:comments) { post.comments }
expose(:comment)
def create
comment.user = current_user
comment.save
CourseNotifier.new(course).notify_course_participants_on_new_discussion(comment)
redirect_to course_home_path(course)
end
...
end
CourseNotifier est la classe où nous plaçons notre logique spécifique à l’application concernant les notifications. Notez que MailgunGateway est injecté comme passerelle par défaut – cela date du temps où nous utilisions plusieurs services d’emailing pour les campagnes, les listes et les emails transactionnels. C’est moins nécessaire maintenant que nous avons consolidé tous les besoins de livraison d’emails vers Mailgun !
class CourseNotifier
attr_reader :course, :gateway
def initialize(course, gateway=MailgunGateway.new)
@course = course
@gateway = gateway
end
def notify_course_participants_on_new_discussion(discussion)
gateway.send_batch_message(
to: notification_recipients(discussion).map(&:email).join(", "),
subject: notification_subject(discussion),
body: discussion_notification_text(discussion),
reply_to: reply_to_address(discussion),
recipient_variables: recipient_variables(
notification_recipients(discussion)
)
)
end
...
private
def notification_recipients(discussion)
course.participants.reject {|participant| participant.email == discussion.user.email }
end
def notification_subject(discussion)
discussion.is_a?(Post) ?
"[Tealeaf Academy] #{discussion.user.name} Posted a New Message on the Discussion Board" :
"[Tealeaf Academy] #{discussion.user.name} Replied to a Message on the Discussion Board"
end
def reply_to_address(discussion)
"reply+#{discussion.token}@messaging.gotealeaf.com"
end
def recipient_variables(recipients)
vars = recipients.map do |recipient|
""#{recipient.email}": {"name":"#{recipient.name}"}"
end
"{#{vars.join(', ')}}"
end
def discussion_notification_text(discussion)
<<-EMAIL
Hi %recipient.name%,
<p>#{discussion.user.name} says on the course dicussion board:</p>
"#{discussion.text}"
<br />
<p>Reply to this email directly or <a href="http://www.gotealeaf.com/courses/#{course.slug}/home">view it on the discussion board</a></p>
EMAIL
end
end
L’adresse replytoaddress est l’endroit où nous insérons le jeton du post dans l’en-tête « Reply-To ». Le contenu des emails est assez simple, nous le plaçons donc simplement ici dans la classe. Si nous avions un style d’email plus élaboré, nous aurions utilisé le rendu de modèle pour le gérer. Avec l’API sendbatchmessage de Mailgun, nous pouvons appeler l’API une seule fois pour envoyer à plusieurs destinataires, et la méthode recipient_variables est l’endroit où nous personnalisons les messages d’email pour chaque destinataire afin d’inclure leurs noms pour ajouter une touche personnelle.
Gestion des messages entrants dans l’application
En nous rendant sur Mailgun, sous « Routes » dans le panneau de configuration, nous avons créé la route suivante :
- Expression de filtre : match_recipient(“reply+(.*)@messaging.gotealeaf.com”)
- Action : forward(“http://www.gotealeaf.com/api/incoming_messages/?post_token=1”)
Lorsqu’un utilisateur répond à un email, il y répond à une adresse email telle que « reply+fj42gq4v@messaging.gotealeaf.com », et cette route transférera l’email à un webhook que nous exposons pour gérer les messages entrants.
class Api::IncomingMessagesController < ApplicationController
skip_before_filter :verify_authenticity_token
def create
user = User.where(email: params['sender']).first
post = Post.where(token: params['post_token']).first
text = params["stripped-text"]
if post && user && text.present?
comment = post.comments.create(user: user, text: text)
CourseNotifier.new(post.course).notify_course_participants_on_new_discussion(comment)
end
head(200)
end
end
Ici, nous utilisons l’email de l’expéditeur pour trouver l’auteur, et utilisons le jeton du post pour trouver le post sous lequel cette réponse doit être regroupée. Mailgun nous donne le texte dépouillé très utile qui supprime la partie du message original pour ne contenir que la réponse réelle ! En fin de compte, nous renvoyons un en-tête 200 pour dire à Mailgun que cette interaction est réussie, sinon Mailgun pensera que notre serveur est en panne et continuera fidèlement d’essayer d’appeler notre webhook.
Le résultat de la mise en œuvre de ce flux de travail est impressionnant : l’activité sur notre forum de discussion a triplé, et les questions obtiennent désormais généralement une réponse dans l’heure, parfois même en quelques minutes, les étudiants peuvent passer à la série de tâches suivante beaucoup plus rapidement et nous sommes très satisfaits de la façon dont cela s’est passé.
« L’utilisation de Mailgun nous permet d’assurer un meilleur service à nos marketeurs. Ils comptent sur nous, et nous comptons sur Mailgun : et cette relation nous aide à maintenir notre crédibilité auprès de nos clients. »