Guides

Notification

Notifications gateway providers allow you to send notifications based on events in Merchello. An popular notification is to send an email to a customer when the customer has completed the checkout process.

Example Usage

Once you have activated a provider, you can now go and set up the provider. Click on the tab which is the type of provider you have activated.

In our case, it was the SMTP provider which is of type 'Notification'. On the right you can see the link 'Add Notification'. Click the link and you'll see 'Email Notification', choose Add and give it a name (i.e. Order Notifications) and a description (Optional).

776776

To configure the Order Confirmation, click on the + icon and you'll see some events we can hook into. We want the first one 'Order Confirmation Message (Pattern Replace)'. Add your Subject, From Email Address and (Optional) description.

778778

Lastly, let's configure the actual message the we'll send. Click on the edit/pencil icon next to your email address. And you'll get a tab with all the final options for this provider. Here you can choose to whom you send the order confirmation and the actual message.

As this message is a 'Pattern Replace' we can pull out data from the order using a pattern like we use in AngularJs to display data i.e. {{BillToName}} or {{PaymentAmount}}

A full list of the items we can use are listed in the Merchello.config and it's always best to check there for the most recent items. Below is a list at the time of writing this documentation.

<patternFormatter>

        <!-- patterns to search and replace can be 
          
          <replace alias="Company" pattern="{{Company}}" replacement="Merchello" replacementInMonitor="false" />
          -->

        <!--
          Depending on the model passed to the "Monitor" responsible for populating the replacements, some of these values will be empty.  For example,
          a MonitorModel that only contains shipment information will not be able to populate Billing information ...
          -->

        <!-- INVOICE -->
        <replace alias="InvoiceKey" pattern="{{InvoiceKey}}" />
        <replace alias="InvoiceNumber" pattern="{{InvoiceNumber}}" />
        <replace alias="InvoiceDate" pattern="{{InvoiceDate}}" />

        <replace alias="InvoiceStatus" pattern="{{InvoiceStatus}}" />
        <replace alias="TotalDiscountPrice" pattern="{{TotalDiscountPrice}}" />
        <replace alias="TotalShippingPrice" pattern="{{TotalShippingPrice}}" />
        <replace alias="TotalCustomPrice" pattern="{{TotalCustomPrice}}" />
        <replace alias="TotalTaxPrice" pattern="{{TotalTaxPrice}}" />
        <replace alias="TotalItemPrice" pattern="{{TotalItemPrice}}" />
        <replace alias="TotalItemPlusCustom" pattern="{{TotalItemPlusCustom}}" />
        <replace alias="TotalPrice" pattern="{{TotalPrice}}" />

        <!-- ADDRESS -->
        <replace alias="BillToName" pattern="{{BillToName}}" />
        <replace alias="BillToAddress1" pattern="{{BillToAddress1}}" />
        <replace alias="BillToAddress2" pattern="{{BillToAddress2}}" />
        <replace alias="BillToLocality" pattern="{{BillToLocality}}" />
        <replace alias="BillToRegion" pattern="{{BillToRegion}}" />
        <replace alias="BillToPostalCode" pattern="{{BillToPostalCode}}" />
        <replace alias="BillToCountryCode" pattern="{{BillToCountryCode}}" />
        <replace alias="BillToEmail" pattern="{{BillToEmail}}" />
        <replace alias="BillToPhone" pattern="{{BillToPhone}}" />
        <replace alias="BillToCompany" pattern="{{BillToCompany}}" />

        <replace alias="ShippedDate" pattern="{{ShippedDate}}" />
        <replace alias="ShipToAddress1" pattern="{{ShipToAddress1}}" />
        <replace alias="ShipToAddress2" pattern="{{ShipToAddress2}}" />
        <replace alias="ShipToLocality" pattern="{{ShipToLocality}}" />
        <replace alias="ShipToRegion" pattern="{{ShipToRegion}}" />
        <replace alias="ShipToPostalCode" pattern="{{ShipToPostalCode}}" />     
        <replace alias="ShipToCountryCode" pattern="{{ShipToCountryCode}}" />
        <replace alias="ShipToName" pattern="{{ShipToName}}" />
        <replace alias="ShipToEmail" pattern="{{ShipToEmail}}" />
        <replace alias="ShipToPhone" pattern="{{ShipToPhone}}" />
        <replace alias="ShipToOrganization" pattern="{{ShipToOrganization}}" />
        <replace alias="ShipToName" pattern="{{ShipToName}}" />
        <replace alias="TrackingCode" pattern="{{TrackingCode}}" />
        <replace alias="ShipMethodName" pattern="{{ShipMethodName}}" />
        <!-- ITERATING THROUGH LINE ITEMS -->


        <!-- LINE ITEMS
        these must be between the IterationStart[Invoice.Items] and IterationEnd[Invoice.Items] so they get repeated in the iteration -
        the pattern is then dynamically changed to
        
        Item.Sku.0 - Item.Name.0 - Item.Price.0 ...
        Item.Sku.1 - Item.Name.1 - Item.Price.1 ...
        Item.Sku.2 - Item.Name.2 - Item.Price.2 ...
        
        before the formatter performs it's replacements the message 
        -->
        <replace alias="LineItemSku" pattern="{{Item.Sku}}" />
        <replace alias="LineItemName" pattern="{{Item.Name}}" />
        <replace alias="LineItemUnitPrice" pattern="{{Item.UnitPrice}}" />
        <replace alias="LineItemQuantity" pattern="{{Item.Quantity}}" />
        <replace alias="LineItemTotalPrice" pattern="{{Item.TotalPrice}}" />

        <!-- PAYMENT -->
        <replace alias="PaymentMethodName" pattern="{{PaymentMethodName}}" />
        <replace alias="PaymentAmount" pattern="{{PaymentAmount}}" />
        <replace alias="PamentReferenceNumber" pattern="{{ReferenceNumber}}" />

    </patternFormatter>

How to create a Custom Notification Provider

Merchello Notifications allow you to send email, twitter, or other information posts based on triggered events. An example of a notification is for a customer to receive an email confirming a placed order or processed credit card sale.

While there are a few standard events (new order) and notifications (SMTP/email), Merchello allows you to build your own to fit your unique business needs.

The Custom Notification Gateway

In this example, I will build a custom SMTP/email-based notification that sends email when a new product is added to the catalog. The email is sent to both warehouse personnel and the sales team alerting them to the new product.

This notification doesn't create new information but uses existing information (the new product) in Merchello to fulfill the notification event.

Development Tasks

The first task is create the class library for the sample notification gateway. Once the library is created and its gateway code is completed and built, the class library will be added to the website.

Test Tasks: BackOffice

The first test task is to prepare the Back office.

Modify the Back office to activate the SMTP notification gateway, then add notification messages for the new event (new product) to both sales and warehouse personal. The email template will include replaceable strings with double curly brackets . When the new product event is triggered, the replaceable strings will be replaced with the properties of the new product.

Test Tasks: Trip the Notification Event

The next test task is to use the Back office - tripping the trigger to send the emails. Create a new Merchello product. Make sure to fill in the following properties when you create the product:

Name
Sku
Barcode
TrackInventory
Height
Length
Width
Weight

These properties are used in the email template. These are not all the Product properties so more could have been added to the email because they are in the monitor replacement code. However, I choose not to include them.

Considerations for your own Custom Notification

In this example, I rely heavily on Merchello. The event is for new Merchello product created in the Back office and the notification information is from the new product object. This made the sample quick and easy.

Your situation may be more complex with your own event and your own information. The trigger can be tripped at any time, and any object can be passed into the monitor.

If you just need to send email in a random spot of the website, feel free to use whatever SMTP framework you already have in place. Merchello notifications don't need to be used in that situation, but they are an option -- albeit a more complicated one.

Visual Studio Solution Organization

For this example, you will want to create a Class Library project. The class library BIN directory will need to have all the Umbraco and Merchello dlls from the website.

In the example code for this document, you will see a Visual Studio solution, with 2 projects. The first project is the class library. The second project is one of the sample Umbraco/Merchello websites.

417417

Add the class library as a reference to the website project. For this example, that is all you need to add the sample shipping gateway to the Merchello website. When you change and build the shipping gateway, the changes are encapsulated in the dll that is updated in the website's /BIN directory.

Make sure the website is set as the Startup Project.

Simple Configurations For This Example

Just adding a reference of the class library to the website skips several steps that you may want to go back and engineer to have a more durable project. The first is to wrap the addition of the class library (and any associated client-side files) into an Umbraco package.

Client Library

For the notification provider class library, you need 3 classes.

ClassInherits FromPurpose
NotificationEventUmbraco.Core
.ApplicationEventHandler
Register event to listen for, pass new product info to monitor for string replacement - converting template into email
NotificationTripperMerchello.Core.Gateways
.Notification.Triggering
.NotificationTriggerBase
registers trigger name and passes object from event to monitor
NotificationMonitorMerchello.Core.Gateways
.Notification.Monitors
.NotificationMonitorBase
Manage the replacement pattern for email

Event class

Start building the class library by registering the event and passing an object through the event. In this example, I selected the Saving event on the ProductService. When the saving event is triggered, the new product's information is passed through.

More than just new products can use the Saving event, so I use the HasProperty check to make sure I'm only firing off the notification trigger if the product does not have an existing identity.

Notice the name "ProductAdd" of the trigger in this class is the same as the name in the class trigger class further down.

MerchelloEvents::ProductService_Saving

namespace MerchelloNotificationExampleProvder.Events
{
    using System;
    using System.Linq;

    using Merchello.Core;
    using Merchello.Core.Events;
    using Merchello.Core.Models;
    using Merchello.Core.Services;

    using Umbraco.Core;
    using Umbraco.Core.Events;
    using Umbraco.Core.Logging;

    public class MerchelloEvents : ApplicationEventHandler
    {
        protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
        {
            // register event
            ProductService.Saving += ProductService_Saving;
        }

        void ProductService_Saving(IProductService sender, SaveEventArgs<IProduct> e)
        {
            foreach (var product in e.SavedEntities)
            {
                // new products only
                if (!product.HasIdentity)
                {
                    // trigger event, pass product
                    Notification.Trigger("ProductAdd", product);
                }
            }
        }
    }
}

Now that the event is wired up, we need something to do when it fires.

Trigger class

The trigger class's purpose is to be invoked by the invent and then notify the monitors. If you wanted to change this class for your own purposes, all you would need is a new class attribute decoration value for "TriggerFor" and a new object model to pass on such as IProduct.

In this version of Merchello, the second parameter of contacts is not used since the email contacts are set in the message in the Back Office. You could have also chosen to pick an object that contains an email address or list, or you could use the contacts list passed through.

ProductAddTrigger class

namespace MerchelloNotificationExampleProvder.NotificationProvider
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

    using Merchello.Core.Gateways.Notification.Triggering;
    using Merchello.Core.Observation;
    using Merchello.Core.Models;

    [TriggerFor("ProductAdd", Topic.Notifications)]
    public class ProductAddTrigger : NotificationTriggerBase<Merchello.Core.Models.IProduct, Merchello.Core.Models.IProduct>
    {
        protected override void Notify(Merchello.Core.Models.IProduct product, IEnumerable<string> contacts)
        {
            this.NotifyMonitors(product);
        }
    }
}

Monitor class

The real work is in the monitor class. This is where you replace strings in the email. The class decoration attribute contains a unique guid, the trigger class and the string that appears in the back office to create the message. Notice that the same IProduct is based from the event, through the trigger, and now to the monitor.

The code below is cherry-picking which properties of IProduct I want to pass through to the email template. You can add all or just a few or create a link with an ID that goes back to the website with information.

ProductAddMonitor

namespace MerchelloNotificationExampleProvder.NotificationProvider
{
    using System.Collections.Generic;
    using System.Linq;
    using Merchello.Core.Formatters;
    using Merchello.Core.Gateways.Notification;
    using Merchello.Core.Gateways.Notification.Monitors;
    using Merchello.Core.Observation;
    using Merchello.Core.Models;

    [MonitorFor("B829266B-B585-4CA2-BCCB-4EBCEE045114", typeof(ProductAddTrigger), "Product Add Message (Pattern Replace)")]
    public class ProductAddMonitor : NotificationMonitorBase<IProduct>
    {
        public ProductAddMonitor(INotificationContext notificationContext)
            : base(notificationContext)
        {
        }

        public override void OnNext(IProduct value)
        {
            if (!Messages.Any()) return;

            var patterns = new Dictionary<string, IReplaceablePattern>()
            {
                { "Name", new ReplaceablePattern("Name", "", value.Name.ToString()) },    
                { "TrackInventory", new ReplaceablePattern("TrackInventory", "", value.TrackInventory.ToString()) },
                { "Barcode", new ReplaceablePattern("Barcode", "", value.Barcode) },
                { "Sku", new ReplaceablePattern("Sku", "", value.Sku) },
                { "Height", new ReplaceablePattern("Height", "", value.Height.ToString()) },
                { "Length", new ReplaceablePattern("Length", "", value.Length.ToString()) },
                { "Width", new ReplaceablePattern("Width", "", value.Width.ToString()) },
                { "Weight", new ReplaceablePattern("Weight", "", value.Weight.ToString()) }
            };

            var formatter = new PatternReplaceFormatter(patterns);

            foreach (var message in Messages.ToArray())
            {
                // send the message
                NotificationContext.Send(message, formatter);
            }
        }
    }
}

Now that the 3 classes are connected, build the class library, make sure the website is set as the start project and debug.

Back Office Setup for Customer Notification Event

Still in the Merchello back office, go to Settings/Notifications. Add a new notification and name it "New Product." This is a category name for all messages created under this category. Add a message and select the new event "Product Add Message," which was the name in the class attribute "MonitorFor."

For the first message, name it "Sales - New Product," and save. Create a second new message and name it "Warehouse - New Product."

19201920

The only difference for these two messages is where it is going (the email address) and what it says (the template). The sales team probably doesn't need to know product measurements but the warehouse team definitely does need to know those to prepare a space in the warehouse.

19201920 19171917

Ready to Test

The custom notification is coded up the class library and built into the website via a reference. The notification gateway is enabled and a notification message has been built on that custom trigger event. Now we are ready to test.

Create a New Product

In the Merchello back office, in the catalog, create a new Product. Save the product. You just triggered the event and you should now have two emails.

Local SMTP Server: SMTP4Dev

While working on email notifications, I looked for a local smtp to install and test. I looked at several but wanted something that didn't let the emails leave my development machine. I settled on SMTP4Dev which has both the source code and the install available from CodePlex. On my Windows 8.1 machine, it works well.