Fallstudien

Wie die Launch School Academy das Engagement der Studierenden verdreifachte

Dieser Beitrag wurde von Kevin Wang, Chief Instructor an der Tealeaf Academy (Launch School), verfasst. Die Tealeaf Academy ist eine Online-Schule für Entwickler und bietet intensive, projektbasierte Online-Bootcamps für die Webentwicklung an. Wenn Sie diesen Beitrag nützlich finden, sollten Sie sich das Angebot ansehen!

An der Tealeaf Academy steht die Schaffung einer „Gemeinsam lernen, gemeinsam Fortschritte machen“-Erfahrung für unsere Studierenden im Mittelpunkt unserer Lehrmethode. Eines unserer wichtigsten Tools ist das Diskussionsforum, in dem Studierende Fragen stellen, Ideen austauschen, bei Hausaufgaben zusammenarbeiten und Lehrer schnell einspringen, um den Studierenden bei Problemen zu helfen. Eine unserer jüngsten Prioritäten bestand darin, die Reibungsverluste bei der Nutzung des Diskussionsforums zu verringern und mehr Diskussionen mit einer ergänzenden E-Mail-Benachrichtigung und einem „Per E-Mail antworten, um im Diskussionsforum zu posten“-Workflow zu fördern.

Sobald wir den untenstehenden Code über die Mailgun Routes API implementiert hatten, verdreifachte sich die Aktivität in unserem Diskussionsforum. Fragen werden nun in der Regel innerhalb einer Stunde, manchmal sogar innerhalb von Minuten, beantwortet, und die Studierenden können viel schneller zur nächsten Reihe von Aufgaben übergehen. So haben wir das gemacht:

Unser Workflow sah folgendermaßen aus:

  1. Wenn ein Beitrag (höchstwahrscheinlich eine Frage) erstellt wird, werden alle Kursteilnehmer durch eine E-Mail-Benachrichtigung informiert.
  2. Kursteilnehmer können direkt aus ihrem E-Mail-Posteingang auf die E-Mail-Benachrichtigungen antworten, ohne sich für den Kurs anmelden zu müssen.
  3. Diese Antwort wird im Online-Diskussionsforum veröffentlicht und auch an andere Kursteilnehmer gesendet, um die Konversation am Laufen zu halten.

Warum wir uns für Mailgun entschieden haben

Der wichtigste Teil dieses Workflows ist das Empfangen und Parsen von eingehenden E-Mail-Nachrichten. Wir haben uns bei verschiedenen E-Mail-Service-Providern umgesehen und uns letztendlich für Mailgun entschieden, weil:

  1. Es ist sehr entwicklerfreundlich – wir sind Entwickler, und Mailgun spricht uns an. Die APIs bieten viele Low-Level-Optionen, die Anpassungen ermöglichen. Wir mögen die Routes im Besonderen – sie bieten eine schöne Abstraktionsschicht, die die Integration mit Apps sehr einfach macht. (siehe unten, wie wir sie verwenden)
  2. Es ist der Service mit dem umfassendsten Funktionsumfang, den wir gefunden haben – wir können Mailgun für Transaktions-E-Mails, Kampagnen sowie E-Mail-Listen nutzen – es ist schön, nur einen einzigen Anbieter zu haben, der alles abwickelt, was wir brauchen.
  3. Der Preis ist angemessen und die Möglichkeit, ein Upgrade auf eine dedizierte IP-Adresse und benutzerdefiniertes DKIM vorzunehmen, ist gut, auch wenn wir dies noch nicht benötigen.
  4. Der Support ist erstklassig. Es gibt einen Live-Chat, in dem ich bei Problemen direkt mit ihren Entwicklern sprechen kann, und er war für uns sehr nützlich, um Probleme zu lösen.

Einrichtung der E-Mail-Infrastruktur

  • Der erste Schritt war die Erstellung einer neuen Domain bei Mailgun. In unserem Fall ist es messaging.gotealeaf.com, die wir für das Senden und Empfangen von E-Mails verwenden.
  • Als Nächstes haben wir ein MailgunGateway als Wrapper für die API von Mailgun erstellt. Dieser Wrapper kümmert sich über unser Konto um alle unsere Interaktionen mit Mailgun. Hier verwenden wir die send_batch_messages API von Mailgun, um HTML-E-Mails zu senden. Sie ermöglicht es uns, mit einem einzigen API-Aufruf eine Nachricht an mehrere Empfänger zu senden. Für zusätzliche Sicherheit bewahren wir unseren API-Schlüssel als Umgebungsvariablen auf dem Server auf. Es gibt auch einen einfachen Zustellungsfilter, sodass in der Entwicklungsumgebung keine E-Mails gesendet werden; in der Staging-Umgebung werden alle E-Mails an Chris (meinen Mitgründer) und mich gesendet, sodass wir Dinge testen können, ohne befürchten zu müssen, unsere Nutzer mit Spam zu belästigen; nur in der Produktionsumgebung werden E-Mails an echte Nutzer gesendet.
                            

                                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
                            
                        

E-Mail-Benachrichtigungen für neuen Beitrag oder Kommentar senden

Sobald ein Beitrag oder Kommentar erstellt wurde, senden wir eine E-Mail-Benachrichtigung an alle Kursteilnehmer. Vorerst senden wir E-Mails synchron, aber wenn wir mehr Nutzer haben, werden wir dies wahrscheinlich an einen Hintergrundjob auslagern wollen.

                            

                                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
                            
                        

Der CourseNotifier ist die Klasse, in die wir unsere anwendungsspezifische Logik für Benachrichtigungen einfügen. Beachten Sie, dass das MailgunGateway als Standard-Gateway eingefügt wird – dies stammt aus der Zeit, als wir noch mehrere E-Mail-Service-Provider für Kampagnen, Listen und Transaktions-E-Mails hatten. Jetzt, da wir alle Anforderungen für die E-Mail-Zustellung bei Mailgun konsolidiert haben, ist dies weniger notwendig!

                            

                                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
                            
                        

Die replytoaddress ist der Ort, an dem wir das Beitrags-Token in die „Reply-To“-Kopfzeile einfügen. Der Inhalt der E-Mails ist recht einfach, daher setzen wir ihn einfach hier in die Klasse. Hätten wir einen aufwändigeren E-Mail-Stil, hätten wir das Rendern von Vorlagen verwendet, um dies zu handhaben. Mit der sendbatchmessage API von Mailgun können wir die API nur einmal aufrufen, um an mehrere Empfänger zu senden, und die recipient_variables Methode ist der Ort, an dem wir E-Mail-Nachrichten für jeden Empfänger anpassen, um ihre Namen hinzuzufügen und eine persönliche Note zu verleihen.

Umgang mit eingehenden Nachrichten in der Anwendung

Wenn wir zu Mailgun wechseln, haben wir unter „Routes“ im Control Panel eine Route wie die folgende erstellt:

  • Filter Expression: match_recipient(“reply+(.*)@messaging.gotealeaf.com”)
  • Aktion: forward(“http://www.gotealeaf.com/api/incoming_messages/?post_token=1”)

Wenn ein Nutzer auf eine E-Mail antwortet, antwortet er an eine E-Mail-Adresse wie „reply+fj42gq4v@messaging.gotealeaf.com“, und diese Route leitet die E-Mail an einen Webhook weiter, den wir bereitstellen, um eingehende Nachrichten zu verarbeiten.

                            

                                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
                            
                        

Hier verwenden wir die E-Mail des Absenders, um den Autor zu finden, und verwenden das Beitrags-Token, um den Beitrag zu finden, unter dem diese Antwort zusammengefasst werden soll. Mailgun gibt uns den sehr nützlichen bereinigten Text, der den ursprünglichen Nachrichtenteil entfernt, sodass nur die tatsächliche Antwort enthalten ist! Am Ende senden wir eine 200er-Kopfzeile zurück, um Mailgun mitzuteilen, dass diese Interaktion erfolgreich war. Andernfalls denkt Mailgun, dass unser Server ausgefallen ist, und wird weiterhin gewissenhaft versuchen, unseren Webhook aufzurufen.

Das Ergebnis der Implementierung dieses Workflows ist beeindruckend – die Aktivität in unserem Diskussionsforum hat sich verdreifacht, und Fragen werden nun in der Regel innerhalb einer Stunde, manchmal sogar in Minuten, beantwortet. Die Studierenden können viel schneller zur nächsten Reihe von Aufgaben übergehen, und wir sind sehr glücklich darüber, wie sich das entwickelt hat.

„Durch den Einsatz von Mailgun können wir einen besseren Service für unsere Marketer gewährleisten. Sie zählen auf uns, und wir zählen auf Mailgun: und diese Beziehung hilft uns, die Glaubwürdigkeit bei unseren Kunden zu erhalten.“
Photo of Paulius Milisauskas
Paulius Milisauskas VP Kundenbetrieb
Bleiben Sie informiert! Erhalten Sie jede Woche wertvolle Inhalte direkt in Ihr Posteingang.
Senden Sie mir den Mailjet-Newsletter. Ich bin mit dem Erhalt des Newsletters einverstanden und weiß, dass ich mich jederzeit unkompliziert wieder abmelden kann.

Prüfen Sie Ihren Posteingang jeden Monat auf Ihren Mailjet Newsletter!