TaCODE Tuesday: A $100 SMS Marketing Campaign, No Kidding

Posted by Pedram Mohammadi on May 16, 2017

Mobile marketing experts claim that there are three key elements behind every successful SMS marketing campaign: first, a carefully crafted text message that includes a valuable offer, exclusivity, a sense of urgency, and a direct call to action that’s easy to understand. Second, a cross-functional team that can help in operating the program; and third, regular measurement of key performance indicators.

However, a successful SMS marketing campaign is only as good as the technology behind it, and this is one vital factor that marketers forget to include on their list. There are a lot of cloud-based text message marketing companies today: SlickText, SumoText and ProTexting, just to name a few. A typical SMS marketing engine subscription costs $49 a month and can send 1,000 messages limited to one to four keywords for the entire subscription duration. This is a bit pricey considering that Zang only charges $0.005 per outbound SMS; for $100 you can send 20,000 messages that aren’t constrained to a one-month time box. Plus, all inbound SMS are free and you don’t have to limit yourself to one to four keywords.

 

tacode-sms-marketing-texting-services.png

Source: Top Ten Reviews

In this week’s TaCode Tuesday, we will teach you how to create a simple Android application to use as a cost-effective marketing tool. This type of app will benefit marketers who want a convenient way of setting up an SMS marketing campaign through their smart phones.

This simple text message marketing app has three main features: generating leads through an SMS opt-in, a user interface to create SMS campaigns, and bulk SMS sending capability.

Before we start, here are a few requirements:

Intermediate knowledge of:

  • Java, Android
  • PHP
  • Cordova
  • JavaScript
  • RESTful APIs
  • Zang APIs

Installation of:

  • Android Studio 2.x
  • Cordova

Let’s start coding!

Feature 1: Generate leads through SMS opt-in.

The first feature enables marketers to engage existing customers and generate new leads through a promo code. The promo code serves two purposes: an opt-in agreement and a voucher giving the customer an added value once they buy.

Before we start developing, create a promo code (it is best to consult with your marketing specialist) that customers will text to opt-in to the SMS campaign. This is important as there are privacy laws protecting consumers from receiving unsolicited text messages. Sending SMS without permission can cost you a lawsuit. For this tutorial, let’s just say we are creating a SMS campaign for a book retailer with promo code “BOOKS45OFF”. Below is the process flow:

 tacode-sms-marketing-process flow.pngFigure 2: Generate leads through SMS opt-in Process Flow

Step 1: Use Zang Inbound SMS API to enable your app to receive SMS

Step 2: Create the code that will recognize the promo code: “BOOKS45OFF” from an inbound SMS

Step 3: Compile and save all mobile numbers which texted the promo code and name it “BOOKS45OFF Campaign”

<?php

$number = $_POST['From'];

$body = $_POST['Body'];

$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */

if (mysqli_connect_errno()) {

printf("Connect failed: %s\n", mysqli_connect_error());

exit();

}

if ($body == 'BOOKS45OFF') {

/* Select queries return a resultset */

if ($result = mysqli_query($link, "INSERT INTO tbl_name(id,telno,datecreated) VALUES($number,$date_today)")) {

//printf("Select returned %d rows.\n", mysqli_num_rows($result));

//TODO: create your custom reply after promo code has been parsed

$status_message = "Thank you we will send your voucher to 24 to 48 hours.";

/* free result set */

mysqli_free_result($result);

}

} else {

$status_message = "Invalid promo code."

}

head

Feature 2 and 3: A user interface allowing marketers to create SMS campaigns and capability to send out SMS in bulk.

 tacode-sms-marketing-process-flow2.png

Figure 3: Create SMS campaign and send bulk SMS Process Flow

Step 4: Create the code that will allow the user to set the budget for the campaign.

 tacode-sms-marketing-set-budget.png

<script language="javascript">

function stepOne() {

var m_budget = document.getElementById("budget").value; localStorage.setItem("budget",m_budget); window.location.href = "stepTwo.html";

}

function stepTwo() {

var m_recipient = document.getElementById("recipient").value; localStorage.setItem("recipient",m_recipient); window.location.href = "stepThree.html";

}

function stepThree() {

var m_message = document.getElementById("message").value; localStorage.setItem("message",m_recipient); window.location.href = "previewEverything.html";

}

</script>

<table border=1>

<tr>

<td>What’s your budget? </td>

<td><input type=”text” name=”budget” id=”budget” value=””/> </td>

<td><input type=”submit” name=”Submit” id=”nextStepOneSubmit” name=”nextStepOneSubmit” onclick=”stepOne()”> </td>

</tr>

</table>

Step 5: Create the code that will import the numbers of the customers who opt-in the campaign from Feature 1.

tacode-sms-marketing-select-recipients.png

<table border=1>

<tr>

<td>Who are the recipients? </td>

<td>

<select id=”recipients” name=”recipients>

<select value=”BOOKS45OFF”> BOOKS45OFF</select>

<select value=”FREEPLANNER”>FREEPLANNER </select>

<select value=”10VOUCHER”>10VOUCHER </select>

</select>

</td>

<td><input type=”submit” name=”Submit” id=”nextStepTwoSubmit” name=”nextStepTwoSubmit” onclick=”stepTwo()”> </td>

</tr>

</table>

Step 6: Create the code that will allow the marketer to compose the message for the SMS campaign.

 tacode-sms-marketing-write-message.png

// previewEverthing.html

<table>

<div id="content">

<div id="budget"> Budget <div id="budgetItem"> <input type="text" id="campaign_budget" value="{$100.00}"></div> </div> <div id="recipient"> Recipient <div id="recipientItem"><input type="text" id="campaign_recipient" value="{Leads from BOOKS45OFF Campaign}"> </div> </div> <div id="message"> Message <div id="messageItem"><input type="text" id="campaign_message" value="{Buy books and get 50% on your...}"> </div> </div> <div id="button"> <div id="yes"> <input type="submit" id="yesButton" name="yesButton" value="Yes" onClick="saveCampaign()" /> </div> </div>

</div>

<script language=”javascript”>

function onLoad() {

document.getElementById("campaign_budget").innerHTML = localStorage.budget; document.getElementById("campaign_recipient").innerHTML = localStorage.recipient; document.getElementById("campaign_message").innerHTML = localStorage.message;

}

function saveCampaign() {

var g_budget = document.getElementById("campaign_budget").value var g_recipient = document.getElementById("campaign_recipient").value; var g_message = document.getElementById("campaign_message").value; //delete previous storage localStorage.removeItem("budget"); localStorage.removeItem("recipient"); localStorage.removeItem("message"); //create new storage basing from user update localStorage.setItem("gBudget",g_budget); localStorage.setItem("gRecipient",g_recipient); localStorage.setItem("gMessage",g_message); //redirect to the last page

window.location.href = "campaignPage.html";

}

</script>

Step 7: Create the code that will allow the marketer to validate the budget, recipients, and message before sending out the SMS campaign.

 tacode-sms-marketing-good-to-go.png

//campaignPage.html

<script language=”javascript”>

function onLoad() {

document.getElementById("campaign_budget").innerHTML = localStorage.gBudget; document.getElementById("campaign_recipient").innerHTML = localStorage.gRecipient; document.getElementById("campaign_message").innerHTML = localStorage.gMessage;

}

function yesCampaign() {

//connect to android javascript bridge for sending the campaign window.JavascriptWebInterface.sendEmailCampaign(localStorage.gBudget,localStorage.gRecipient,localStorage.gMessage); window.location.href = “success.html”;

}

function noCampaign() {

//TODO //create your handler for ending sessio..

}

</script>

<table>

<div id="content">

<div id="budget"> Budget <div id="budgetItem"> {$100.00}</div> </div> <div id="recipient"> Recipient <div id="recipientItem">{Leads from BOOKS45OFF Campaig} </div> </div> <div id="message"> Message <div id="messageItem">{Buy books and get 50% on your...} </div> </div> <div id="button"> <div id="yes"> <input type="submit" id="yesButton" name="yesButton" value="Yes" onClick="saveCampaign()" /> </div> <div id="no"> <input type="submit" id="noButton" name="noButton" value="No" onClick="endSession()" /> </div> </div>

</div>

</table>

Step 8: Create the code that will show a confirmation page of the successful SMS blast.

 tacode-sms-marketing-sent.png

MainActivity.java

package io.cordova.zang;

import android.app.Activity;

import android.app.ProgressDialog;

import android.content.Context;

import android.content.pm.ActivityInfo;

import android.graphics.Bitmap;

import android.util.Log;

import android.webkit.WebChromeClient;

import android.view.View;

import android.webkit.WebSettings;

import android.webkit.WebView;

import android.widget.ProgressBar;

import android.os.Handler;

import android.os.Bundle;

import org.apache.cordova.*;

import com.app.sencor.utils.JavascriptWebInterface;

import com.zyramedia.cordova.stripe.CordovaStripe;

public class MainActivity extends CordovaActivity

{

@Override

public void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

super.init();

WebView wView = (WebView)appView.getEngine().getView();

WebSettings wSettings = wView.getSettings();

wSettings.setJavaScriptEnabled(true);

wView.addJavascriptInterface(new JavascriptWebInterface(this),"Android");

//wView.addJavascriptInterface(new CordovaStripe(this),"stripe");

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

super.appView.clearHistory();

super.appView.clearCache();

super.loadUrl("file:///android_asset/www/index.html");

}

}

//JavascriptWebInterface.java

package com.app.sencor.utils;

import android.widget.Toast;

import android.content.Context;

import android.webkit.JavascriptInterface;

import android.app.AlertDialog;

import android.content.Context;

import android.content.DialogInterface;

import android.content.Intent;

import android.os.Bundle;

import android.util.Log;

import java.io.ByteArrayInputStream;

import java.io.PrintWriter;

import java.io.StringWriter;

import java.nio.charset.Charset;

import java.nio.charset.StandardCharsets;

import java.util.HashMap;

import java.util.Map;

import java.util.StringTokenizer;

import com.stripe.Stripe;

import com.stripe.exception.StripeException;

import com.stripe.model.Charge;

import com.stripe.net.RequestOptions;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.UnsupportedEncodingException;

public class JavascriptWebInterface

{

Context mContext;

//private static InputStream jsonInputStream = null;

//private static String json = "";

/** Instantiate the interface and set the context */

public JavascriptWebInterface(Context c)

{

mContext = c;

}

/** Show a toast from the web page */

@JavascriptInterface

public void showToast(String toast)

{

Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();

}

//create a class that will hold the SMS information

public class SMS

{

private String smsTo;

private String smsBody;

private String smsFrom;

private String smsStatusCallback;

private String smsAllowMultiple = true;

 

//getter and setter

public String getSMSTo() {

return this.smsTo;

}

public String getSMSBody() {

return this.smsBody;

}

public String getSMSFrom() {

return this.smsFrom;

}

public String getSMSStatusCallback() {

return this.smsStatusCallback;

}

public String getSMSAllowMultiple() {

return this.smsAllowMultiple;

}

//TODO: placeholder only

public DummyPlaceholder() {}

}

 

#JavascriptInterface

/*

curl -X POST 'https://api.zang.io/v2/Accounts/{AccountSid}/SMS/Messages.json' -u

'{AccountSid}:{AuthToken}' -d 'To=XXX-XXX-XXXX&From=XXX-XXX-XXXX&Body=This is an SMS sent from Zang'

*/

public void sendSMSCampaign(String smsBudget, String smsRecipient, String smsMessage)

{

InputStream inputStream = null;

String result = "";

try {

HttpClient httpclient = new DefaultHttpClient();

//Zang.io Send sms api

HttpPost httpPost = new HttpPost("{https://api.zang.io/v2/Accounts/{AccountSid}/SMS/Messages.json}");

String json = "";

JSONObject jsonObject = new JSONObject();

SMS sms = new SMS;

//setup your campaign variables from the user input

jsonObject.accumulate("To", smsRecipient;

jsonObject.accumulate("From", sms.getSMSFrom());

jsonObject.accumulate("Body", smsMessage);

jsonObject.accumulate("AllowMultiple", sms.getSMSAllowMultiple());

json = jsonObject.toString();

StringEntity se = new StringEntity(json);

// set httpPost Entity

httpPost.setEntity(se);

 

// Set some headers to inform server about the type of the content

httpPost.setHeader("Accept", "application/json");

httpPost.setHeader("Content-type", "application/json");

 

// Execute POST request to the given URL

HttpResponse httpResponse = httpclient.execute(httpPost);

 

// receive response as inputStream

inputStream = httpResponse.getEntity().getContent();

 

// convert inputstream to string

if(inputStream != null)

result = convertInputStreamToString(inputStream);

//parse your "result" JSON

String status_message = "SMS Campaign Sent!"

else

result = "Problem sending Campaign.";

}

catch (Exception e) {

Log.d("InputStream", e.getLocalizedMessage());

}

return result;

}

 

 

public boolean isConnected(){

ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Activity.CONNECTIVITY_SERVICE);

NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();

if (networkInfo != null && networkInfo.isConnected())

return true;

else

return false;

}

}

//Example successful result after invoking the zang send sms api

{

"api_version": "v2",

"sid": "{SmsSid}",

"account_sid": "{AccountSid}",

"date_created": "Tue, 24 Jul 2012 14:08:23 +0000",

"date_updated": "Tue, 24 Jul 2012 14:08:24 +0000",

"date_sent": "Tue, 24 Jul 2012 14:08:24 +0000",

"to": "+17325551234",

"from": "+14245551234",

"body": "Test message sent from TelAPI!",

"status": "sent",

"direction": "outbound-api",

"price": "0.070000",

"uri": "/v2/Accounts/AC5521767e53d04deeb0a06f660cee50f9/SMS/Messages/{SmsSid}.json"

}

And… were done!

This simple text message marketing app is a form of permission based marketing - a technique introduced by Seth Godin in 1999. Godin is an American author, entrepreneur, marketer, and public speaker. According to him:

Permission Marketing encourages consumers to participate in a long-term, interactive marketing campaign in which they are rewarded in some way for paying attention to increasingly relevant messages. Imagine your marketing message being read by 70% of the prospects you send it to (not 5% or even 1%). Then imagine that more than 35% respond. That's what happens when you interact with your prospects one at a time, with individual messages, exchanged with their permission over time. Permission marketing is anticipated, personal, relevant. Anticipated-people look forward to hearing from you Personal-the messages are directly related to the individual. Relevant-the marketing is about something the prospect is interested in.

When done correctly, SMS marketing can not only grow one’s business in as fast as 24 hours, but can also be a valuable tool that can foster customer satisfaction and loyalty leading to increased revenue. Carl’s Jr. realized this in 2013 when they launched SMS marketing and earned $14 for every $1 spent on the SMS campaign. Redbox used text messages to foster loyalty among their already huge customer base producing over 1.5 million SMS and 400,000 participating customers in just 10 days. It’s easy to build your own cost effective marketing tool through Zang; start with a free trial.

Start building on Zang

Topics: Ideas, TaCode Tuesday, cPaaS, SMS