Server Side Marketing Automations

Server Side Marketing Automations are Automation scenarios invoked in automated way from your Appgain.io App backend , examples of use cases are :

  • 🙋 Customer OnBoarding welcome drip messages to teach the new user about your App/Website USPs, Features.
  • 💰 Achieve First Purchase to motivate the new users to do the first order/purchase if they have installed the App since N days with No Purchase has been done.
  • 👏 On Purchase to reward the users for doing a purchase and motivate them to do a
  • 🎂 Birthday Gift send automated discount codes for customers on their birthdays

How it Works ?

To use Appgain.io Server Side Marketing Automations , you need to

1-Create Automation Rule

Create Automation Rule at Appgain.io Dashboard that will determine what messages will be sent , when each message will be sent and over which channel , for example Abandoned Cart Reminder Rule will be like this :

Message Title Message Channel Content URL GracePeriod (in Hours)
You Left The Happiness In Your Cart My Cart Push Notification Are we breaking up?💔 MyApp://Cart 1 Hour
still overthinking? Email We all hesitate! Just go with the one you liked most 😉 MyApp://Cart 24 Hours

2-Fire Automation Rule Trigger Point

  1. Creating CloudFunctions

  2. Call CloudFunctions using crontab or queue style , currently this is not part of Appgain Dashboard so you need contact our support via chat to setup the automation firing cron jobs

CloudFunctions Templates

Customer OnBoarding

this CF is used to Retarget Users who Just Installed App , and send them Push Notifications , SMS or Email Campaigns

Parse.Cloud.define("WelcomeOfferAutomatorOptin", async (request) => {
  let { projectId, apiKey } = request.params;

  if (!(projectId && apiKey)) throw "projectId and apiKey are required";

  try {
    const query = new Parse.Query("_User");
    const optinKey = "automatorWelcomeOfferOptin";
    const optinKeyDate = "automatorWelcomeOfferOptinDate";
    const triggerName = "OnAppInstall";
    query.doesNotExist(optinKey);
    query.limit(9999999999);
    let users = await query.find();

    if (users.legth == 0) return;

    let userIds = [];
    for (let user of users) {
      userIds.push(user.get("userId"));
    }
    let automatorURL = getAutomatorUrl(projectId, triggerName);
    let res = await Parse.Cloud.httpRequest({
      method: "POST",
      url: automatorURL,
      headers: {
        "Content-Type": "application/json",
        appApiKey: apiKey,
      },
      body: {
        users_ids: userIds,
      },
    });

    for (let user of users) {
      user.set(optinKey, true);
      user.set(optinKeyDate, new Date());
      user.save(null, { useMasterKey: true });
    }
    console.log("trigger res: ", res.text);
  } catch (error) {
    console.log(
      "error at WelcomeOfferAutomatorOptin: ",
      error.message || error.data || error
    );
  }
});

Install since N days with No Purchase

  • AutomatorOptin

this CF is used to Retarget Users who Installed App Since N days and numOfOrders =0 ,
for example if you need to Retarget Users Who Installed App Since 5 Days and not done any Orders yet.

Parse.Cloud.define("AutomatorOptin", async (request) => {
 let { segmentName, automatorName } = request.params;
 let { projectId, apiKey } = request.params;

 if (!(segmentName && automatorName && projectId && apiKey))
   throw "segmentName, automatorName,projectId and apiKey are required";

 try {
   var query = new Parse.Query("AppSegments");
   const optinKey = "automatorOnNoFirstPurchaseOptin";
   const optinKeyDate = "automatorOnNoFirstPurchaseOptinDate";

   query.equalTo("name", segmentName);
   query.limit(9999999999);
   let segment = await query.find();

   if (segment.legth == 0) throw "There is no Segment with that name.";

   segment = segment[0];

   if (segment.get("userIds").legth == 0) throw "This Segment has no Users.";

   query = new Parse.Query("_User");
   query.containedIn("userId", segment.get("userIds"));
   query.limit(9999999999);

   let users = await query.find();

   if (users.legth == 0)
     throw "This Segment's Users doesn't match any User record.";

   for (let user of users) {
     let userId = user.get("userId");
     let automatorURL = getAutomatorUrl(projectId, automatorName, userId);
     let res = await Parse.Cloud.httpRequest({
       method: "GET",
       url: automatorURL,
       headers: {
         "Content-Type": "application/json",
         appApiKey: apiKey,
       },
     });

     user.set(optinKey, true);
     user.set(optinKeyDate, new Date());
     user.save(null, { useMasterKey: true });
     console.log("trigger res: ", res.text);
   }
 } catch (error) {
   console.log(
     "error at AutomatorOptin: ",
     error.message || error.data || error
   );
 }
});


  • AutomatorOptout

this CF is Used to Cancel Automation Campaigns, in other words if the user done the first purchase so it will remove him from the automation flow

Parse.Cloud.define("AutomatorOptout", async (request) => {
  let { segmentName, automatorName } = request.params;
  let { projectId, apiKey } = request.params;

  if (!(segmentName && automatorName && projectId && apiKey))
    throw "segmentName, automatorName,projectId and apiKey are required";

  try {
    var query = new Parse.Query("AppSegments");
    const optinKey = "automatorOnNoFirstPurchaseOptout";
    const optinKeyDate = "automatorOnNoFirstPurchaseOptoutDate";

    query.equalTo("name", segmentName);
    query.limit(9999999999);
    let segment = await query.find();

    if (segment.legth == 0) throw "There is no Segment with that name.";

    segment = segment[0];

    if (segment.get("userIds").legth == 0) throw "This Segment has no Users.";

    query = new Parse.Query("_User");
    query.containedIn("userId", segment.get("userIds"));
    query.limit(9999999999);

    let users = await query.find();

    if (users.legth == 0)
      throw "This Segment's Users doesn't match any User record.";

    for (let user of users) {
      let userId = user.get("userId");
      let automatorURL = getAutomatorUrl(projectId, automatorName, userId);
      console.log("automatorURL: ", automatorURL);
      let res = await Parse.Cloud.httpRequest({
        method: "DELETE",
        url: automatorURL,
        headers: {
          Accept: "application/json",
          appApiKey: apiKey,
        },
      });

      user.set(optinKey, true);
      user.set(optinKeyDate, new Date());
      user.save(null, { useMasterKey: true });
      console.log("trigger res: ", res.text);
    }
  } catch (error) {
    console.log(
      "error at AutomatorOptout: ",
      error.message || error.data || error
    );
  }
});

Purchase

this CF is calling OnPurchase Automator on each Purchase Action , and send Push Notifications , SMS or Email Campaigns , its uses AfterSave Trigger to be fired as soon as a transaction is logged and no need for cronjob to fire it

Parse.Cloud.afterSave("PurchaseTransactions", async (request) => {
  try {
    let userId = request.object.get("userId");
    if (!userId) return;

    query = new Parse.Query("configs");
    let apiKey, projectId;
    let configs = await query.find();
    for (let config of configs) {
      if (config.get("key") == "projectId") projectId = config.get("value");
      else if (config.get("key") == "apiKey") apiKey = config.get("value");
    }

    let automatorURL = getAutomatorUrl(projectId, "OnPurchase", userId);
    let res = await Parse.Cloud.httpRequest({
      method: "GET",
      url: automatorURL,
      headers: {
        "Content-Type": "application/json",
        appApiKey: apiKey,
      },
    });
    console.log("trigger res: ", res.text);
  } catch (error) {
    console.log(
      "error at PurchaseTransactions: ",
      error.message || error.data || error
    );
  }
});

function getAutomatorUrl(projectId, triggerName, userId) {
  if (userId)
    return `https://automator.appgain.io/automessages/${projectId}/firevent/${triggerName}/${userId}`;
  return `https://automator.appgain.io/automessages/${projectId}/firevent/${triggerName}`;
}