Skip to content
Snippets Groups Projects
Commit a8ae6415 authored by Allen Gilliland's avatar Allen Gilliland
Browse files

split follow-up emails into 2 distinct paths.

parent fc55f139
Branches
Tags
No related merge requests found
......@@ -93,8 +93,8 @@
[email msg-type]
{:pre [(string? email)
(u/is-email? email)
(contains? #{"active" "inactive"} msg-type)]}
(let [subject (if (= "inactive" msg-type)
(contains? #{"abandon" "follow-up"} msg-type)]}
(let [subject (if (= "abandon" msg-type)
"[Metabase] Help make Metabase better."
"[Metabase] Tell us how things are going.")
data-quote (quotation/random-quote)
......@@ -102,7 +102,7 @@
:logoHeader true
:quotation (:quote data-quote)
:quotationAuthor (:author data-quote)}
(if (= "inactive" msg-type)
(if (= "abandon" msg-type)
{:heading "We’d love your feedback."
:callToAction "It looks like Metabase wasn’t quite a match for you. Would you mind taking a fast 5 question survey to help the Metabase team understand why and make things better in the future?"
:link "http://www.metabase.com/feedback/this-thing-sucks"}
......
......@@ -118,3 +118,8 @@
[reset-token]
{:pre [(string? reset-token)]}
(str (setting/get :-site-url) "/auth/reset_password/" reset-token))
(defn instance-created-at
"The date the instance was created. We use the :date_joined of the first user to determine this."
[]
(db/sel :one :field [User :date_joined] (k/order :date_joined :ASC) (k/limit 1)))
......@@ -17,45 +17,61 @@
[metabase.task :as task]))
(declare send-follow-up-email!)
(declare send-follow-up-email! send-abandonment-email!)
(def ^:private ^:const follow-up-emails-job-key "metabase.task.follow-up-emails.job")
(def ^:private ^:const follow-up-emails-trigger-key "metabase.task.follow-up-emails.trigger")
(defonce ^:private follow-up-emails-job (atom nil))
(defonce ^:private follow-up-emails-trigger (atom nil))
(setting/defsetting follow-up-email-sent "have we sent a follow up email to the instance admin?" false :internal true)
;; triggers the sending of all pulses which are scheduled to run in the current hour
(def ^:private ^:const abandonment-emails-job-key "metabase.task.abandonment-emails.job")
(def ^:private ^:const abandonment-emails-trigger-key "metabase.task.abandonment-emails.trigger")
(defonce ^:private abandonment-emails-job (atom nil))
(defonce ^:private abandonment-emails-trigger (atom nil))
(setting/defsetting abandonment-email-sent "have we sent an abandonment email to the instance admin?" false :internal true)
;; 2 weeks of inactivity after 30 days of total install
;;
;; this sends out a general 2 week email follow up email
(jobs/defjob FollowUpEmail
[ctx]
;; 1. if we've already sent the follow-up email then we are done
;; if we've already sent the follow-up email then we are done
(when-not (= "true" (follow-up-email-sent))
;; figure out when we consider the instance created (join date of oldest user)
(when-let [instance-created (-> (k/select user/User
(k/fields :date_joined)
(k/order :date_joined :ASC)
(k/limit 1))
first
:date_joined)]
;; 2. we need to be 2+ weeks (14 days) from creation to send the follow up
;; figure out when we consider the instance created
(when-let [instance-created (user/instance-created-at)]
;; we need to be 2+ weeks (14 days) from creation to send the follow up
(when (< (* 14 24 60 60 1000)
(- (System/currentTimeMillis) (.getTime ^java.sql.Timestamp instance-created)))
;; 3. we need access to email AND the instance must be opted into anonymous tracking
(send-follow-up-email!)))))
;; this sends out an email any time after 30 days if the instance has stopped being used for 14 days
(jobs/defjob AbandonmentEmail
[ctx]
;; if we've already sent the abandonment email then we are done
(when-not (= "true" (abandonment-email-sent))
;; figure out when we consider the instance created
(when-let [instance-created (user/instance-created-at)]
;; we need to be 4+ weeks (30 days) from creation to send the follow up
(when (< (* 30 24 60 60 1000)
(- (System/currentTimeMillis) (.getTime ^java.sql.Timestamp instance-created)))
;; we need access to email AND the instance must be opted into anonymous tracking
(when (and (email/email-configured?)
(let [tracking? (setting/get :anon-tracking-enabled)]
(or (nil? tracking?) (= "true" tracking?))))
(send-follow-up-email!))))))
(send-abandonment-email!))))))
(defn task-init
"Automatically called during startup; start the job for sending pulses."
"Automatically called during startup; start the job for sending follow up emails."
[]
;; build our job
;; FollowUpEmail job + trigger
(reset! follow-up-emails-job (jobs/build
(jobs/of-type FollowUpEmail)
(jobs/with-identity (jobs/key follow-up-emails-job-key))))
;; build our trigger
(reset! follow-up-emails-trigger (triggers/build
(triggers/with-identity (triggers/key follow-up-emails-trigger-key))
(triggers/start-now)
......@@ -63,28 +79,54 @@
;; run once a day
(cron/cron-schedule "0 0 12 * * ? *"))))
;; submit ourselves to the scheduler
(task/schedule-task! @follow-up-emails-job @follow-up-emails-trigger))
(task/schedule-task! @follow-up-emails-job @follow-up-emails-trigger)
;; AbandonmentEmail job + trigger
(reset! abandonment-emails-job (jobs/build
(jobs/of-type AbandonmentEmail)
(jobs/with-identity (jobs/key abandonment-emails-job-key))))
(reset! abandonment-emails-trigger (triggers/build
(triggers/with-identity (triggers/key abandonment-emails-trigger-key))
(triggers/start-now)
(triggers/with-schedule
;; run once a day
(cron/cron-schedule "0 0 12 * * ? *"))))
;; submit ourselves to the scheduler
(task/schedule-task! @abandonment-emails-job @abandonment-emails-trigger))
(defn- send-follow-up-email!
"Send an email to the instance admin following up on their experience with Metabase thus far."
[]
(try
;; grab the oldest admins email address, that's who we'll send to
(when-let [admin (db/sel :one user/User :is_superuser true (k/order :date_joined))]
;; check for activity and use that to determine which email we'll send
;; inactive = no users created, no activity created, no dash/card views (past 7 days)
(let [last-user (c/from-sql-time (db/sel :one :field [user/User :date_joined] (k/order :date_joined :DESC) (k/limit 1)))
last-activity (c/from-sql-time (db/sel :one :field [activity/Activity :timestamp] (k/order :timestamp :DESC) (k/limit 1)))
last-view (c/from-sql-time (db/sel :one :field [view-log/ViewLog :timestamp] (k/order :timestamp :DESC) (k/limit 1)))
seven-days-ago (t/minus (t/now) (t/days 7))
message-type (if (and (t/before? last-user seven-days-ago)
(t/before? last-activity seven-days-ago)
(t/before? last-view seven-days-ago))
"inactive"
"active")]
(messages/send-follow-up-email (:email admin) message-type)))
;; we need access to email AND the instance must be opted into anonymous tracking
(when (and (email/email-configured?)
(let [tracking? (setting/get :anon-tracking-enabled)]
(or (nil? tracking?) (= "true" tracking?))))
;; grab the oldest admins email address, that's who we'll send to
(when-let [admin (db/sel :one user/User :is_superuser true (k/order :date_joined))]
(messages/send-follow-up-email (:email admin) "follow-up")))
(catch Throwable t
(log/error "Problem sending follow-up email" t))
(finally
(setting/set :follow-up-email-sent "true"))))
(defn- send-abandonment-email!
"Send an email to the instance admin about why Metabase usage has died down."
[]
;; grab the oldest admins email address, that's who we'll send to
(when-let [admin (db/sel :one user/User :is_superuser true (k/order :date_joined))]
;; inactive = no users created, no activity created, no dash/card views (past 7 days)
(let [last-user (c/from-sql-time (db/sel :one :field [user/User :date_joined] (k/order :date_joined :DESC) (k/limit 1)))
last-activity (c/from-sql-time (db/sel :one :field [activity/Activity :timestamp] (k/order :timestamp :DESC) (k/limit 1)))
last-view (c/from-sql-time (db/sel :one :field [view-log/ViewLog :timestamp] (k/order :timestamp :DESC) (k/limit 1)))
two-weeks-ago (t/minus (t/now) (t/days 14))]
(when (and (t/before? last-user two-weeks-ago)
(t/before? last-activity two-weeks-ago)
(t/before? last-view two-weeks-ago))
(try
(messages/send-follow-up-email (:email admin) "abandon")
(catch Throwable t
(log/error "Problem sending abandonment email" t))
(finally
(setting/set :abandonment-email-sent "true")))))))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment