In most situations emails just go out the door and people assume they arrive, get opened, and get actioned. In the real world this is not the case. I intend to assign this to myself but may not get to it for a few weeks, this is just sharing my thoughts ahead of time for feedback.
Some questions / use cases that this new report should be able to easily answer:
- How many emails were sent, out of them how many were 'sent', 'opened' and 'actioned'?
- If emails are not arriving, are they emails to a particular domain? Often any filtering issues will be highly dependant on the recipient domains policies, so it needs to very easy to determine that say all emails to yahoo are failing. (will also have admin docs linking to moodle wiki re SPF / DKIM / DMARC around this)
- After we have made any changes (technical delivery, templates, changes to subject / email copy etc) has the engagement level changed? ie keep historical stats
- Do certain types of messages have very low engagement? We should filter the report by message type, ie we may be very interested in engagement level for some emails, but not worried at all with low engagement for say forum emails.
- The open metric may be highly skewed depending on the email client, eg gmail opens images by default, others do not. So we need to clearly break down opening rates by client. We may need to extend core_useragent or make a new class core_emailuseragent.
It would be possible to add a new message output plugin which could do most of this, but there are too many emails send outside of the message api which are of interest for reporting needs. I also considered adding a new hook somewhere in email_to_user so it could be a plugin, but it also needs touch points in a few other places to make it all work, and is probably also of general interest to many admins so thought it may be better in core.
- First make an admin option to turn it on. Not everyone will want or need it, and it could produce a lot of data so will default to off.
- all outgoing emails will be filtered and 2 things added:
- in the html version a beacon img reference added to the email footer. The image will default to a 1x1 gif but can be configured to be a logo or something useful, possibly added via a template.
- in both text and html versions any links will have an extra tracking query param tacked on (we could also implement this via a redirection service and this is plan B if the query method proves problematic)
- create a summary email record will be stored with basic metadata including which part of moodle / message type created the email, and what course / module. Any emails in the tracking table will be stored as local part and domain part to make later reporting faster and easier.
- create a beacon service which stores when the email was 'viewed', and a timestamp
- create the action link tracking. We need to decide whether to treat clicking on any url in the email as the same action or whether to track each url on it's own. Probably any engagement is a good enough metric for the flag. There are two ways the tracking could be done, possibly a hybrid of both may be needed:
- detect incoming links from emails via the special query param and store the second 'actioned' flag. It may be preferable to implement it in require_login() near the end to capture whether someone has actually clicked on the link and gone all the way to the destination rather than hitting a login screen and then stopping. But this won't work for non authenticated pages, so it needs to be captured somewhere else as well, maybe in $OUTPUT->header() or similar with a request scope flag so it's not recorded twice.
- have a redirect service which sets the flag and redirects on. Unlike the query param method this is slower, and we won't know who the user is etc, but this method could also be used to track links in emails to non-moodle url's.
- create a cron task which condenses historical data, ie reduces to just keys % stats per domain per time period (day? week? configurable)
- create reports which summarize and can be filtered by domains and message types, and optionally link more deeply into moodle specific data
- also have a 'sent' flag, which would be either set correctly if moodle is using smtp directly and the email was sent, OR some other means such as a postfix sent milter, or postfix log file parsing and feedback mechanism. This would also be flagged if the email wasn't sent due to a users bounces or email preferences. See also the email_failed event.
- MessageId seems the natural key for all tracking, but it will generate pretty long urls - that may mean that the redirect tracking is preferable? The text only emails will be horrible to read - I can't see a clean way around this. Maybe we just don't track text emails?
- If we do a redirection service it should be stateless, so jam the message id local part and destination url path part together and then base64, then encode
- MessageId is usually null except for the forum and is generated in phpmailer, so need to generate that in email_to_user instead
- Need to have config for how long we keep MessageId tracking alive for, 1 week / 1 month / 3 month / etc
- Message api will need to pass in context and maybe other info via $userfrom
- May be useful to have admin options to exclude certain emails by message type
- Email client user agent lists: http://www.adammcfarland.com/2015/03/31/a-list-of-email-client-user-agents-plus-our-most-popular-client/
Many cloud MTA's like mandrill etc can also give you free tracking like this - however there are some advantages to doing it at the application level, in particular being able to give filtered summary reports to the people sending the messages eg teachers, and also we can leverage addition application specific information such as linking the report to different types of emails, or even deeper such as completion tracking, or forum read status (ie any more definitive source of engagement rather than simple whether a link was clicked)