How to Get In-app Messaging Right
If you build apps that rely on continuously engaging with the customer, there are chances that shipping the finished app is not enough to drive that engagement. I am sure you have been on a shopping site that offered you discounts because you added a product to cart.
When such cart campaigns are done right, it makes a difference on whether you purchase more item or not. If done wrong, it could lead to a terrible experience that might cost you a customer.
Here’s an example of such experience and we are going to use it as example for this article.
And here’s a GitHub repo if you want to build along.
Push Notification vs In-App Messaging
It is easy to confuse the difference between push notification and in-app messaging.
Let’s say you hypothetically have an app called Popper on your phone. If your phone is idle and you get a message from Popper, that is a push notification. On the contrary, if you’re scrolling through feeds on Popper and a notification slides in from the top or bottom, that is likely an in-app message.
With push notifications, the app needs to ask for permission to send a message to the user. The user must have given the app the permission to send messages. Permissions are REQUIRED (at least for iOS and Android) to send push notifications.
As a developer, in-app messaging is your land of freedom. You do not need permissions to do anything. Its your app, so your rules! The only downside is that you can only show it when a customer is on the app. That said, this unlimited amount of freedom can be easily abused.
Why do you need a cloud service for in-app messaging
Since its your world, your rules, your app, you can do things however you want without relying on the device, on a service, etc. To be honest, that is true. But we are not only talking about messaging, we are also talking about getting it right.
You can have a global event in your app that listens to users’ actions and shows pop ups based on those actions. But how do you know which users have interacted with the pop up? How do you segment users that responded negatively and positively? How do you give control to marketing department to send in-app messaging if they don’t have developers?
These questions will force you to build a service from scratch but you don’t have to. Amplify’s in-app messaging uses Amazon Pinpoint Analytics services to provide the toolset you need. With this option you can add in-app messaging in a short period of time.
How to get in-app messaging right
It’s 2021 and everybody hates unsolicited notifications but there is a few reason you wouldn’t mind that one message:
- Segmentation and timing
- Native experience
- Product pairing
Segmentation and timing
When you segment users, they feel special. Here’s what I mean — if I put you in a segment called musician because you bought a piano, you will feel special when I inform you that a guitar is now 50% off.
It wouldn’t make sense to tell you that basketballs are 50%. From my perspective as the business, I just wanted to inform my customers. From my customer’s perspective, the customer doesn’t care about basketballs.
Segmentation without timing is also annoying and sometimes customers can feel attacked. Don’t just ask me to buy guitars for 50%, one hour after buying a piano. Space it, give me time.
Native experience
This one seems to be a no-brainer but because in-app messaging is one of those afterthought feature, most of them look like they were not thought through. You can’t have a dark mode checkout with a message confirmation button that is in light mode.
Make your interfaces and also the experience feel consistent with reference to all other features in your app.
Product pairing
Product pairing is similar to segmentation but goes one level deeper. In segmentation we talked about offering a customer 50% off a guitar because they bought a piano. Product pairing works better when they have not checked out.
For pairing to work well, you have to ensure that the paired products solve a problem for the user. Pair guitars with tuners, karaoke boxes with singing courses, swimsuits with towels, you get the point.
In-app Messaging with Amplify
In-app messaging is now natively available in Amplify and here are the steps to set it up:
- Create an Amplify project with Pinpoint Analytics enabled
- Attach IAM policy to Pinpoint
- Create campaigns and segments
- Dispatch and listen to in-app messages
You can setup in-app messaging for any kind of frontend/mobile framework that is supported by Amplify. Currently, there are UI components for only React Native but you can write custom components for other frameworks. The demo will be based on React so I will show you how to create a custom UI for notifications.
Create an Amplify Project
Create a new project and run the init command:
amplify init
If you are not familiar with how to set up an Amplify project, refer to the Getting Started docs to get you up to speed.
Run the following command to add Amazon Pinpoint to your project:
amplify add analytics
When asked to choose a provider, select Amazon Pinpoint. Choose the default answers for the rest of the questions.
Push your Amplify setup to the cloud with the following:
amplify push
Amplify will generate an aws-exports.js
file in your src
folder. Your AWS credentials are stored here and Amplify libraries need it when making requests. Add the following before the closing curly braces:
const awsmobile = {
...
"Notifications": {
"InAppMessaging": {
"AWSPinpoint": {
"appId": "<pinpoint-project-id>",
"region": "<aws-region>",
},
},
},
};
You can get the Pinpoint project ID by going to Pinpoint home in your AWS console. You should see the project you just created on the list:
The region
should be the same value as the generated value for aws_mobile_analytics_app_region
in the aws-exports.js
file.
Create and Attach IAM Policy to Pinpoint
Next you need to grant your users access to the Pinpoint service you have just created. This step will end up being baked into the automatic process for you. So you won’t have to do it manually.
That said, you need to create it in the AWS console by following these steps.
Create Campaigns and Segments
This is the most important step for setting up in-app messaging. We talked about segmentation at the beginning of the article and why it is very important for conversion. This step shows how to set segmentation up.
From Pinpoint home, select the Pinpoint project you have just created. Next click Campaigns from the sidebar menu and click the Create a campaign button.
Give the Campaign a name, choose in-app messaging as the channel and click next:
On the Choose a segment page, choose Create a segment and give the segment a name. Click Next afterwards.
On the Create your message page, choose Create a new in-app message. This is where you can customize your UI components. As you customize the UI, you will get a preview on the phone screen.
What makes Pinpoint great is that anyone without a developer experience can create campaigns and messages for those campaigns. Someone from marketing department can customize this as deep as what the message looks like.
The last step is to create an event. This event is what you dispatch from your app to notify Amplify that a user has perfomed an action to trigger the in-app notification.
Give the event a name and optionally choose some attributes that can trigger this campaign:
In the example above, I want the cart_event to be triggered only when the event payload object contains a name property with a value that contains any of the above attribute values.
Scroll down to choose the start and end date for the campaign and select the timezone for the time you’ve set:
Click Next and the console will show you a page to review the campaign. Click the Launch Campaign button at the bottom right of the review page. The date must be 15mins in the future so you will get a validation error if the time is ealiar.
Dispatch and Listen to in-App Messages
To the fun part!
Install Amplify library, In-app UI library and other supporting dependencies:
npm install aws-amplify@in-app-messaging aws-amplify-react-native@in-app-messaging amazon-cognito-identity-js @react-native-community/netinfo @react-native-async-storage/async-storage @react-native-picker/picker react-native-get-random-values react-native-url-polyfill
Setup the required polyfills and configure the library with the aws-exports
config in the App.js
file:
import 'react-native-get-random-values';
import 'react-native-url-polyfill/auto';
import { AppRegistry } from 'react-native';
import { name as appName } from './app.json';
import Amplify from 'aws-amplify';
import awsExports from './src/aws-exports';
Amplify.configure(awsExports);
function App() {
}
AppRegistry.registerComponent(appName, () => App);
export default App;
In the App.js
component, tell Amplify to sync in-app messages between Pinpoint and the app:
/*
Summarized version of:
https://github.com/christiannwamba/in-app-cart/blob/master/App.js
*/
import { Notifications } from 'aws-amplify';
export default function App() {
React.useEffect(() => {
Notifications.InAppMessaging.syncMessages();
}, []);
}
You also need to wrap your tree with the InAppMessagingProvider
and render InAppMessageDisplay
component. This is how the UI library knows to show the user a message when an event is triggered:
/*
Summarized version of:
https://github.com/christiannwamba/in-app-cart/blob/master/App.js
*/
import {
InAppMessagingProvider,
InAppMessageDisplay,
} from 'aws-amplify-react-native';
function App() {
React.useEffect(() => {
Notifications.InAppMessaging.syncMessages()
}, [])
return (
<InAppMessagingProvider>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={({ navigation }) => ({
title: 'Shop',
headerRight: ({}) => (
<CartIcon
onPress={() => navigation.navigate('Cart')}
title="Info"
/>
),
})}
/>
<Stack.Screen name="Cart" component={CartScreen} />
<Stack.Screen name="Product" component={ProductScreen} />
</Stack.Navigator>
</NavigationContainer>
<InAppMessageDisplay />
</InAppMessagingProvider>
);
}
When you call syncMessages()
, Amplify will start asking Pinpoint for all the messages that has been created if any. You want to call this function as early as possible in your app. That’s why I am calling it at the top of the component tree.
Here is how to dispatch and listen to events from your app:
/*
Summarized version of:
https://github.com/christiannwamba/in-app-cart/blob/master/screens/ProductScreen.js
*/
export default function ProductScreen({ route, navigation }) {
const { productId } = route.params;
const [product, setProduct] = React.useState([]);
const [inCart, setInCart] = React.useState(false);
React.useEffect(() => {
async function fetchProduct() {
const models = await DataStore.query(ProductModel, productId);
const cartItem = await DataStore.query(Cart, (c) =>
c.productId('eq', productId)
);
setProduct(models);
setInCart(!!cartItem.length);
}
fetchProduct();
}, [productId]);
async function addToCart() {
await DataStore.save(
new Cart({
productId,
})
);
const event = { name: 'cart_event', attributes: { name: product.name } };
Analytics.record(event);
setInCart(true);
}
}
When you call the record
function, you have to give it an object that contains the event name you created when you created the campaign. Notice how I’ve also set the prduct name attributes. Unless the attribute matches the attribute you set in your Pinpoint dashboard, this event will not fire. Once the event is dispatched, Pinpoint keeps a record of it and also notifies all active listeners.
Conclusion
As a recap, remember to segment your users based on their behavior and customize your UI so it feels native to your customers. Amplify gives you the tools you need to identify users based on the data you’ve collected from them. Take advantage of the feature when segmenting users.
Clean up
Now that you have finished this walkthrough, we recommend that you delete your Amplify app if you aren’t going to use it anymore. This ensures that your resources won’t be abused in the event that someone gains access to your project’s credentials.
To delete all of the local Amplify associated files and the Amplify project in the backend, go to your Amplify console, select the app you want to delete, and expand the dropdown in the top right to delete your app.
Alternatively, you can run the following command in your working directory:
`amplify delete`
This action cannot be undone. Once the project is deleted, you cannot recover it and will have to reconfigure the categories and the project configuration files if you need to use the project again.