Dynamic Pacing Schedules ======================== The Schedules app allows course teams to automatically email learners in self-paced courses. The emails are designed to keep learners engaged with a course. Learners receive these messages at important milestones in their learning. The author of a self-paced course opts learners into one of two “Schedule Experiences”. Learners either receive Weekly Course Highlight Messages, or a combination of Recurring Nudges and Upgrade Reminders. The app can send all three message types “out of the box” - Recurring Nudges - Upgrade Reminders - Weekly Course Highlight Messages Recurring Nudges encourage learners to return to self-paced courses at regular intervals. The app sends nudges three days and ten days after a learner enrolls in a course. Upgrade Reminders ask learners to purchase their course’s Verified certificate. The reminders are sent two days before their course’s upgrade deadline, or two days before the course’s end date (whichever date occurs sooner). Weekly Course Highlight Messages tell learners what to look forward to in the coming week of a course. Course authors provide “section highlights” when authoring a course in Studio. The app sends a weekly email with these highlights listed in the message. The app introduces a Schedule object to the edX codebase. Learners receive Schedules when they enroll in self-paced courses. The app uses Schedules to determine which learners to message. In the future, the Schedules app may be extended or changed to support more complicated communication patterns. For example, something that takes into account the user's progress through the course. Glossary -------- - **Schedule**: Stores the day a learner enrolls in a course and the learner's "upgrade deadline". This information allows us to personalize learners' experiences in self-paced courses so that events happen relative to the learner's schedule, not the course's schedule. - **Schedule Experience**: Defines the set of emails that a learner receives. The two Schedule Experiences are: - “Recurring Nudge and Upgrade Reminder” - “Course Updates” - **Upgrade Deadline**: The date before which a learner is encouraged to purchase a verified certificate. By default, a Schedule imposes a "soft" upgrade deadline (meaning, a suggested, but not final, date) 21 days from when a learner enrolled in a course. A self-paced course imposes a "hard" upgrade deadline that is the course-wide expiration date for upgrading on the course. A Schedule uses whichever date is earlier. - **Course Update**: We refer to "Weekly Course Highlight Messages" as "Course Updates" in the code. In contexts outside of this app, Course Updates refer to bulk-emails manually sent out by course instructors and for the blocks of text that course instructors can add to the top of the course outline. We plan on removing this term from this app's code to avoid confusion. - **Section**: From our `documentation <http://edx.readthedocs.io/projects/edx-%20partner-course-staff/en/latest/developing_course/course_sections.html#what-is-a-section>`__, “A section is the topmost category in your course. A section can represent a time period in your course, a chapter, or another organizing principle. A section contains one or more subsections.” For the purposes of Weekly Section Highlights Messages, we assume that a section contains a week’s worth of learning material. - **Weekly Section Highlights**: A list of topics that learners will encounter in a section of a course. Course authors enter section highlights in the Studio UI. - **Resolver**: A Python class that identifies which learners to message and sends them emails. We create a Resolver subclass to manage each message type. An “UpgradeReminderResolver” sends Upgrade Reminder messages, a “RecurringNudgeResolver” sends Recurring Nudge messages, and a “CourseUpdateResolver” sends Weekly Section Highlight Messages. - **MessageType**: A Python class that represents a kind of email message. It specifies the Django template the app uses the render the email. `MessageType is an ACE concept <https://edx-ace.readthedocs.io/en/latest/modules.html#edx_ace.message.MessageType>`__. - **Task**: A `Celery <http://docs.celeryproject.org/en/latest/index.html>`__ asynchronous class/function that is run in a separate process from the main Django LMS process. In the app, a task is created to email groups of learners. We bin learners to distribute the amount of work each task performs. We email each bin's worth of learners in a task. - **Bin**: In the Schedules app, we divide the learners we are emailing into N “bins” (by default, N is 24). We do this to evenly distribute the number of emails each task must send. - **Email Backend**: An external service that ACE will use to deliver emails. Right now, ACE only supports `Sailthru <http://www.sailthru.com/>` as an email backend. Running the Management Commands ------------------------------- There are three management commands in the Schedules app. Each command sends a message type: ``send_recurring_nudge``; ``send_upgrade_reminder``; and ``send_course_update``. You must specify the Site for which you are sending emails in the command: :: ./manage.py lms send_recurring_nudge example.com Make sure to specify your development environment with the “settings” flag. For example, if you are running a command in docker devstack, you can use: :: ./manage.py lms --settings devstack_docker send_recurring_nudge example.com You can override the “current date” when running a command. The app will run, using the date you specify as its "today": :: ./manage.py lms --settings devstack_docker send_recurring_nudge example.com --date 2017-11-13 If the app is paired with Sailthru, you can override which email addresses the app sends to. The app will send all emails to the address you specify: :: ./manage.py lms --settings devstack_docker send_recurring_nudge example.com --override-recipient-email developer@example.com These management commands are meant to be run daily. We schedule them to run automatically in a Jenkins job. You can use a similar automation tool, like “cron”, to schedule a daily run of the app. Configuring A.C.E. ------------------ These instructions assume you have already setup an Open edX instance or are running devstack. See the `Open edX Developer’s Guide <http://edx.readthedocs.io/projects/edx-developer-guide/en/latest/>`__ for information on setting them up. The Schedule app relies on ACE. When live, ACE sends emails to users through Sailthru. You can instead configure ACE to write emails to the local filesystem, which can be useful for debugging. File Back-end ~~~~~~~~~~~~~ Edit the ``lms/envs/common.py`` or ``lms/envs/private.py``\ and add/change the following: .. code:: python ACE_CHANNEL_SAILTHRU_DEBUG = True By default, your devstack should be configured to use the ``file_email`` ACE channel. This ACE channel saves the emails to ``/path/to/your/devstack/src/ace_messages/*.html`` on your host machine (the host path corresponds to ``/edx/src/ace_messages/`` in your devstack docker container). To view the emails, open the saved files in your browser. Sailthru Back-end ~~~~~~~~~~~~~~~~~ To configure ACE to send emails to users’ email addresses, add a `Sailthru <http://www.sailthru.com/>`__ back-end configuration. See the `edx-ace documentation <https://edx-ace.readthedocs.io/en/latest/getting_started.html#sailthruemailchannel-settings>`__ for instructions on setting up a Sailthru API key and secret. Make sure to add the following settings in either ``lms/envs/common.py`` or ``lms/envs/private.py``: .. code:: python ACE_CHANNEL_SAILTHRU_DEBUG = False ACE_ENABLED_CHANNEL = ['sailthru_email'] ACE_ENABLED_POLICIES = ['bulk_email_optout'] ACE_CHANNEL_SAILTHRU_TEMPLATE_NAME = '<insert_sailthru_template_name_here>' Django Settings --------------- These settings populate links in the emails to external social media, marketing websites, app stores, etc. Edit the ``lms/envs/common.py`` or ``lms/envs/private.py`` and add/change the following: .. code:: python FEATURES = { 'ENABLE_MKTG_SITE': True, } MKTG_URLS = { 'ROOT': '<insert_lms_url_here>', } SOCIAL_MEDIA_FOOTER_URLS = { 'tumblr': '<insert_tumblr_url_here>', 'reddit': '<insert_reddit_url_here>', 'twitter': '<insert_twitter_url_here>', 'google_plus': '<insert_google_plus_url_here>', 'youtube': '<insert_youtube_url_here>', 'linkedin': '<insert_linkedin_url_here>', 'meetup': '<insert_meetup_url_here>', 'facebook': '<insert_facebook_url_here>', } MOBILE_STORE_URLS = { 'google': '<insert_play_store_url_here>', 'apple': '<insert_app_store_url_here>', } CONTACT_MAILING_ADDRESS = '<insert_physical_address_here>' Configuration Flags ------------------- Configuring Schedule Creation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Make sure a Site has been created at ``<lms_url>/admin/sites/site``. ScheduleConfig ^^^^^^^^^^^^^^ In the Django admin panel at ``<lms_url>/admin/schedules/scheduleconfig/`` create a ScheduleConfig and link it to the Site. Make sure to enable all of the settings: - ``create_schedules``: enables creating new Schedules when new Course Enrollments are created. - ``hold_back_ratio``: ratio of all new Course Enrollments that should NOT have a Schedule created. Roll-out Waffle Flag ^^^^^^^^^^^^^^^^^^^^ There is one roll-out related course waffle flag that we plan to delete called ``schedules.create_schedules_for_course``, which, if the ``ScheduleConfig.create_schedules`` is disabled, will enable schedule creation on a per-course basis. Self-paced Configuration ^^^^^^^^^^^^^^^^^^^^^^^^ Schedules will only be created for a course if it is self-paced. A course can be configured to be self-paced by going to ``<studio_url>/admin/self_paced/selfpacedconfiguration/`` and adding an enabled self paced config. Then, go to Studio settings for the course and change the Course Pacing value to “Self-Paced”. Note that the Course Start Date has to be set to sometime in the future in order to change the Course Pacing. Configuring Upgrade Deadline on Schedule ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The upgrade reminder message type depends on there being a date in the ``upgrade_deadline`` field of the Schedule model. Up-sell messaging will also be added to the recurring nudge and course updates message types when an upgrade deadline date is present. DynamicUpgradeDeadlineConfiguration models ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In order to enable filling in the ``upgrade_deadline`` field of new Schedule models created, you must create and enable one of the following: - A DynamicUpgradeDeadlineConfiguration toggles the feature for all courses globally. - A OrgDynamicUpgradeDeadlineConfiguration toggles the feature for all courses in a particular organization. - A CourseDynamicUpgradeDeadlineConfiguration toggles the feature for a particular course. The CourseDynamicUpgradeDeadlineConfiguration takes precedence over the OrgDynamicUpgradeDeadlineConfiguration which takes precedence over the global DynamicUpgradeDeadlineConfiguration. The “deadline days” field specifies how many days from the day of the learner’s enrollment will be their soft upgrade deadline on the Schedule model. Verified Course Mode ^^^^^^^^^^^^^^^^^^^^ The ``upgrade_deadline`` will only be filled for a course if it has a verified course mode. To add a verified course mode to a course, go to ``<lms_url>/admin/course_modes/coursemode/`` and add a course mode linked with the course with the "Mode" equal to "verified". Configuring Email Sending ~~~~~~~~~~~~~~~~~~~~~~~~~ .. scheduleconfig-1: ScheduleConfig ^^^^^^^^^^^^^^ The ScheduleConfig model at ``<lms_url>/admin/schedules/scheduleconfig/`` also has fields which configure enqueueing and delivering emails per message type: - ``enqueue_*``: allows sending email tasks of this message type to celery. - ``deliver_*``: allows delivering emails through ACE for this message type. .. roll-out-waffle-flag-1: Roll-out Waffle Flag ^^^^^^^^^^^^^^^^^^^^ Another roll-out related course waffle flag that we plan to delete called ``schedules.send_updates_for_course`` will enable sending specifically the course updates email per-course. Configuring Highlights UI in Studio ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The button and modal on the course outline page that allows course authors to enter section highlights can be toggled globally by going to ``<lms_url>/admin/waffle/switch/`` and adding an active switch called ``dynamic_pacing.studio_course_update``. This is a roll-out related waffle switch that we will eventually delete. Configuring a Learner’s Schedule ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Emails will only be sent to learners who have Schedule ``start_date``\ s or ``upgrade_deadline``\ s and ScheduleExperience that match the criteria for the message type. Recurring Nudge ^^^^^^^^^^^^^^^ - Learners must have the ScheduleExperience type of "Recurring Nudge and Upgrade Reminder". - Their Schedule ``start_date`` must be 3 or 10 days before the current date. Upgrade Reminder ^^^^^^^^^^^^^^^^ - Learners must have the ScheduleExperience type of “Recurring Nudge and Upgrade Reminder”. - Their Schedule ``upgrade_deadline`` must be 2 days after the current date. Course Update ^^^^^^^^^^^^^ - Learners must have the ScheduleExperience type of “Course Updates”. - Their Schedule ``start_date`` must be 7, 14, or any increment of 7 days up to 77 days before the current date. Litmus ------ When designing email templates, it is important to test the rendered emails in a variety of email clients to ensure that they render correctly. EdX uses a tool called `Litmus <http://litmus.com/>`__ for this process. To begin using Litmus, follow these steps: 1. Make sure that ACE is configured to use Sailthru (see instructions above). 2. Go to the `Litmus checklist page <https://litmus.com/checklist>`__ and start a new checklist. 3. The checklist will provide you with an email address to which you will send a test email. 4. Send an email. Use one of the management commands with the `--override-recipient-email` flag. Use the Litmus email you got in step 3 as the flag value. :: ./manage.py lms --settings devstack_docker send_recurring_nudge example.com --override-recipient-email PUT-LITMUS-ADDRESS-HERE Using the Litmus Browser Extenstion to test emails saved as local files ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1. Configure your devstack to use the "file_email" channel for ACE (see instructions above). 2. Install the Litmus `chrome browser extension <https://chrome.google.com/webstore/detail/litmus/makmhllelncgkglnpaipelogkekggpio>`__. 3. Send an email by running the management command. This should save the email to a file. 4. Open the saved file in chrome on your host. It should be in `/path/to/your/devstack/src/ace_messages/*.html`. 5. Open the Litmus extension. 6. When you regenerate emails, you can easily refresh the previews in Litmus.