Skip to main content

Notifications

This system allow different types of notifications, and there are specific services that contain the logic needed, using CountryProvider.

!!!info Logging For all notifications, the NotificationLog model tracks each delivery request with its parameters, as well as delivery status whenever this is possible. !!!

Email​

This uses 2 different providers based on email type: there can be event email actions and newsletter. The proper CountryProvider is loaded based on the value of additional_data, in the send_type key, that can actually be event or newsletter.

Transactional​

The classic transactional email sent to the final user (that can both be the booking's user or the salon owner), and customer.io is used for that.

The customer.io system is an event-based system, so we're sending events that triggers workflows on customer.io side, as well as email content and UI.

Event's data are:

  1. ACTIVITY NAME the name of the event
  2. the parameters to compose the email:
    • any attribute needed (appoitment's time, venue's name, etc.)
    • recipient that contains email of the user that should receive the email
    • template that indicates if the venue is a UALA client or a Treatwell client
    • language that indicates the event's locale (when available)

There is a CountryProvider per each Country, and in each customer.io workspace all the campaigns are defined and maintained. Originally this also meant a single locale per Country, but has changed during the years with the introduction of language attribute, and gradually integrated.

Users​

There are 2 types of users:

:::code source="../../uala-main/app/services/notifications/email_service.rb" title="uala-main/app/services/notifications/email_service.rb" range="35-38" :::

Identified users​

This user type directly links a uala-backend's User to customer.io's people and allow to have a set of attributes related to the user itself, as well as the creation of custom journeys based on user's behaviour. The user_id on both systems matches.

This was intially meant to address only UALA Marketplace's users, and its gradual shutdown reduced the number of events sent to identified users.

When sending an identified event, a identify API request is triggered before the event, that upsert the user in customer.io system. Then, the track API request includes the user_id.

Anonymous users​

This is more an event type than a user type, and it's basically an event with no correlation with others, meaning it's not linked to a user journey. These event's attributes must include recipient (email) and customer_first_name (name) in order to send the event to the "unsubscribed" user.

How to add a new event​

There is a large set of events, and they can be found under uala-main/app/services/notifications/email_service/ folder. A lot of examples of different behaviour are available.

To create the service that send the email the proper way is to inherit from Notifications::EmailService overriding the "abstracts" methods. One of those is event_properties, that defines the data to send to customer.io in a JSON format that should be composed in agreement with the Customer Relation Team.

:::code source="../../uala-main/app/services/notifications/email_service.rb" title="uala-main/app/services/notifications/email_service.rb" range="44-66" :::

To test that the event is created correctly on customer.io it's advisable to deploy the branch on a dev env. Those environments are connected to the customer.io develop environment: https://fly.customer.io/env/5243. To check the event in the development environment it's possible to search it in the page Activity Logs (both for identified and anonymous events) or in the page Data Index where it's also possible to go to the event's page.

Then the Customer Relation Team should approve that the Event's data sent are enough to create the email that will be delivered to the users.

Newsletters​

The newsletters notification flow is a service offered to the salon to create and manage its own marketing notifications to its customers. Through Newsletter, NewsletterExecution, NewsletterLayout and NotificationCredit models, a basic marketing service is set up, with the possibility to use predefined Treatwell's models (NewsletterLayout), a credit system (NotificationCredit), and tracking features (NewsletterExecution).

For this type of notifications, another external provider is used, called brevo (formerly sendinblue), that is more similar to a SMTP provider than customer.io, but it's still an email provider with a set of endpoints for that.

Differently on what happens with customer.io, for brevo our system is building and sending to the external provider the full email's HTML.

Recipients filters​

There are a set of usable filters to be applied to recipients list of a newsletter, and they can be found in uala-main/app/services/newsletters/filters/ folder. Each of it defines a SQL query for Customer to be applied given a set of input parameters.

For example: :::code source="../../uala-main/app/services/newsletters/filters/shown_in_last_days_filter.rb" title="uala-main/app/services/newsletters/filters/shown_in_last_days_filter.rb" range="3-17" :::

Notification credits​

A credit system is available based on the NotificationCredit model and transactions are tracked with NotificationCreditUsage model. While the first contains information about current credit (total_sms_available_count, total_email_available_count), the second tracks each inward (credit recharge) and outward (sms/email sent) transaction for it.

Execution types​

A newsletter can be cyclic, meaning that it repeats during the time (daily, weekly or monthly), scheduled so that it's postponed (scheduled_at) and immediate.

SMS​

As per email, there can be event email actions and newsletter. The proper CountryProvider is loaded based on the value of additional_data, in the send_type key, that can actually be event or newsletter.

!!!info Newsletter For marketing (newsletter) SMS notifications, see Newsletters, the same email logics apply for SMS. !!!

To send SMS, the current external provider is MessageBird, both for transactional and marketing communications.

The external provider simply receives a request from our system with required parameters to let the recipient properly receive the SMS:

  • originator: string containing the sender name; this can both be "Treatwell", but also a custom sender
  • phone: E.164 representation of the recipient phone number
  • text: the SMS text body

General rules and restrictions​

  • SMS can be sent only to the customer with the phone number provided in the customer's profile (the phone field in the customer's profile)
  • SMS can be sent only to the customer that allowed to receive SMS notifications (the should_receive_sms_notifications flag in the customer's profile)
  • We send SMS only in case of venues that allowed to send SMS notifications (the should_*_by_sms group of fields in the venue)
  • We send SMS only in case of venues that didn't reach the SMS limit (plan_limits field in the venue)

How to add a new event​

SMS events are defined in sms_service.rb file as methods and then called from other application's points (mainly async jobs).

:::code source="../../uala-main/app/services/notifications/sms_service.rb" title="uala-main/app/services/notifications/sms_service.rb" range="139-144" :::

As you can see, the should_notify? method is called, as multiple checks can be performed before a notification is sent.

Custom sender​

Through custom originator it's possible to set the name of the SMS' sender, following defined rules.

Not all events uses the custom sender, there are some checks in place to decide whether it can be used and what's its value: :::code source="../../uala-main/app/services/notifications/sms_service.rb" title="uala-main/app/services/notifications/sms_service.rb" range="283-291" :::

GSM encoding​

For SMS character encoding, the GSM 03.38 standard is used, and it contains a limited number of options, compared to the large Unicode.

When the text fits the GSM requirements, it is possible to send up to 160 characters (packed in up to 140 octets) in one SMS message; when the number of characters exceed 160, concatenated sms are then sent.

To let the text use only GSM characters, multiple actions are in place:

  • remove non-GSM accents
  • upcase greek text (because only upcased greek letters are availabile in GSM)
  • fix confusables

:::code source="../../uala-main/app/services/notifications/sms_service.rb" title="uala-main/app/services/notifications/sms_service.rb" range="590-628" :::

Webhook​

MessageBird supports webhook and NotificationLog is updated with information coming from the webhook in its controller (uala-main/app/controllers/api/v1/country_providers/message_bird_controller.rb).

Push​

!!!info Newsletter There are only transactional push notifications, so no newsletter/marketing flow here. !!!

To send push notification, the current external provider is OneSignal.

For a User to receive push notifications its needed to login in the mobile application, where there is an action that calls a backend endpoint (uala-main/app/controllers/api/v3/account/one_signal_players_controller.rb) to register the user in the OneSignal provider (the user device is then called player), and the link between OneSignal (CountryProvider) and the User is stored with ExternalProviderCustomer model.

How to add a new event​

Push notifications events are defined in push_service.rb file as methods and then called from other application's points (mainly async jobs).

:::code source="../../uala-main/app/services/notifications/push_service.rb" title="uala-main/app/services/notifications/push_service.rb" range="92-96" :::

As you can see, the should_notify? method is called, as multiple checks can be performed before a notification is sent.

Notification translations​

For push notifications with OneSignal, all translations of title/subtitle/body are sent to the user and then the preferred locale is selected. Given this, all push notification texts are translated by the backend application, as usual in the uala-core/config/locales/ folder.

Delivery status​

OneSignal doesn't provide a webhook implementation as per SMS with MessageBird, so for each push notification sent, a OneMinuteMaidJob is scheduled after 1 minute, and in it the notification status is checked using OneSignal API.

When a notification should be sent​

Many checks and logics are in place to prevent an unwanted notification to be sent, and all of them are defined in the uala-main/app/services/notifications/notification_module.rb file:

:::code source="../../uala-main/app/services/notifications/notification_module.rb" title="uala-main/app/services/notifications/notification_module.rb" range="113-172" :::

Types​