Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

CleverTap Event Adjustment

Search Term Event

Event Name: Search Keyword Event Properties:

ParametersExample ValueNoteTrigger
search_term“cafe”Keywordwhen klik enter or search on search field

Search Filter Event

Event Name: Search Filter Event Properties:

ParametersExample ValueNoteTrigger
package_typeayce,pppackage type
sort_byprice ascsort
price_min0price filter min
price_max3200price filter max
price_typeper_packprice filter type
cuisine_id7,228cuisine id
cuisine_nameChinese,Halalcuisine name
location_id1269
location_nameAmarin Plaza
location_typeshopping_mall
facility_id1006
facility_nameMall Restaurant

Example onSearchFinish:

{
	"search_param": {
		"page_number": 1,
		"page_size": 10,
		"cuisine_ids": [
			{
				"id": 7,
				"name": "Chinese"
			},
			{
				"id": 228,
				"name": "Halal"
			}
		],
		"location_ids": [
			{
				"id": 1269,
				"name": "Amarin Plaza",
				"type": "shopping_mall"
			}
		],
		"facility_ids": [
			{
				"id": 1006,
				"name": "Mall Restaurants"
			}
		],
		"package_type": "ayce,pp",
		"price_filter": {
			"min": 0,
			"max": 3200,
			"price_type": "per_pack",
			"symbol_currency": "฿"
		},
		"sort_by": "price asc"
	},
	"no_result_found": false,
	"search_total": 8
}

Save Selected Cuisine from Survey

  • Advise on Recommendations setup in CT (CT Team)
    • HH noted that the Recommendations seem to be producing the same list of restaurants. CT team to advise and validate setup 

Current payload from onSurveySubmitted:

{
	"cuisine_ids": [
		"14",
		"225",
		"35",
		"255",
		"20"
	],
// get from name_en
	"cuisine_names_en": [
		"Chinese",
		"International",
		"Japanese",
		"Sushi",
		"Dim Sum"
	],
// get from name_th
	"cuisine_names_th": [
		"วยเตี๋ยว",
		"นานาชาติ",
		"ของหวาน",
		"อาหารริมทาง",
		"อาหารทะเล"
	],
	"city_id": "1"
}

Android:

ArrayList<String> cuisineId = new ArrayList<String>();
cuisineId.add("14");
cuisineId.add("225");
cleverTap.setMultiValuesForKey("cuisine_id", cuisineId);

ArrayList<String> cuisineName = new ArrayList<String>();
cuisineName.add("Chinese");
cuisineName.add("Japanese");
cleverTap.setMultiValuesForKey("cuisine_name_en", cuisineName);

ArrayList<String> cuisineName = new ArrayList<String>();
cuisineName.add("ก๋วยเตี๋ยว");
cuisineName.add("นานาชาติ");
cleverTap.setMultiValuesForKey("cuisine_name_th", cuisineName);

iOS:

CleverTap.sharedInstance()?.profileSetMultiValues(["14", "225"], forKey: "cuisine_id")

CleverTap.sharedInstance()?.profileSetMultiValues(["Chinese", "Japanese"], forKey: "cuisine_name_en")

CleverTap.sharedInstance()?.profileSetMultiValues(["ก๋วยเตี๋ยว", "นานาชาติ"], forKey: "cuisine_name_th")

Reference: https://developer.clevertap.com/docs/concepts-user-profiles#manually-updating-multi-value-user-profile-properties

Store User's last booking as part of User Properties

Store User's last booking as part of User Properties. We will update property when do charged event, can get it from API get reservation detail. {{ base_api  }}/reservations/{{ booking_id}}.json member + access token/ {{ base_api  }}/reservations/gbqRB/detail.json guest

  • Last booking merchant id => data.attributes.restaurant_id
  • Last booking cuisine / experience category => included[restaurants].attributes.cuisine
  • Last booking merchant location / geolocation => included[restaurants].attributes.location
  • Last booking transacted value => data.attributes.total_price Android
HashMap<String, Object> profileUpdate = new HashMap<String, Object>();
profileUpdate.put("last_booking_merchant_id", "997");
profileUpdate.put("last_booking_cuisine", "American");
profileUpdate.put("last_booking_location", "Amarin");
profileUpdate.put("last_booking_value", 2598);

cleverTap.pushProfile(profileUpdate);

iOS

let profile: Dictionary<String, AnyObject> = [
    "last_booking_merchant_id": "997",
    "last_booking_cuisine": "American",
    "last_booking_location": "Amarin",
    "last_booking_value": 2598]

CleverTap.sharedInstance()?.profilePush(profile)

Reference: https://developer.clevertap.com/docs/concepts-user-profiles#manually-updating-single-value-user-profile-properties

Registerhttps://web.hungryhub.com/register We have campaign that trigger user to register if they do booking with guest user. If we click that url will open register page. But in case user already sign in we'll redirect to profile page.

For website can we show pop up when open that link.

App Inboxhttps://web.hungryhub.com/notifications  This one that we have on notification icon. Android:

ct.showAppInbox(styleConfig)

Ref: https://developer.clevertap.com/docs/android-app-inbox iOS:

if let inboxController = CleverTap.sharedInstance()?.newInboxViewController(with: style, andDelegate: self) {        let navigationController = UINavigationController.init(rootViewController: inboxController)        self.present(navigationController, animated: true, completion: nil)  }

Ref: https://developer.clevertap.com/docs/app-inbox-ios

Vouchershttps://web.hungryhub.com/profile/voucher  We'll open my voucher page in profile

Near Mehttps://web.hungryhub.com/restaurants/near-me  we need to get user permission first to get user location before redirecting to search by latitude and longitude

Update 2 Aug 23

  • How to store survey results as User Properties for existing Users
  • Store cuisine name EN and TH for survey data
  • Add the used promo code in Charge Event
  • Add Transaction Completed Event for Backend

Backend

Survey results as User Properties for existing Users In our existing app, hundreds of users already full survey forms and we only save cuisine_id array in local form. So, we need API to get cuisine name list. My suggestion, we can use API {{ base_api }}/cuisines.json and put some query cuisine_ids, and then return cuisine array data. In example: {{ base_api }}/cuisines.json?cuisine_ids=10,14,...

{
	"data": [
		{
			"id": "10",
			"type": "cuisines",
			"attributes": {
				"name": "นานาชาติ",
				"name_en": "International",
				"name_th": "นานาชาติ",
				"total_restaurants": 311,
				"cover": {
					"url": "https://hhstaging.hungryhub.com/uploads/restaurant_tag/cover/10/cuisine-international.jpeg",
					"thumb_url": "https://hhstaging.hungryhub.com/uploads/restaurant_tag/cover/10/cuisine-international.jpeg"
				}
			}
		},
		{
			"id": "14",
			"type": "cuisines",
			"attributes": {
				"name": "ก๋วยเตี๋ยว",
				"name_en": "Noodle",
				"name_th": "ก๋วยเตี๋ยว",
				"total_restaurants": 311,
				"cover": {
					"url": "https://hhstaging.hungryhub.com/img/hh_logo.png",
					"thumb_url": "https://hhstaging.hungryhub.com/img/hh_logo.png"
				}
			}
		},
......

From that data we'll update user properties again for that specific users.

Add Transaction Completed Event Event to capture when a booking has been completely fulfilled (ie User has completed dining / stay) Eg: when points issued to customer or when status updated to arrived https://developer.clevertap.com/docs/upload-events-api 

Create API get single restaurant by query Currently for linked content clevertap doesn't support custom path in the API. Our API: {{ base_api }}/restaurants/280.json Expected: {{ base_api }}/restaurants.json?restaurant_id=280 Can we create new API to prive restaurant data like that?

Client Update

Survey results as User Properties for existing Users Our existing app might be only store data like this:

{
	"cuisine_ids": [
		"14",
		"225",
		"35",
		"255",
		"20"
	],
	"city_id": "1"
}

Since we only show survey for the first time, we don't have cuisine name data from users. So, we need to hit an API with cuisine_ids filter to get cuisine name and store it to users properties clevertap. API: {{ base_api }}/cuisines.json?cuisine_ids=10,225,16,....

{
	"data": [
		{
			"id": "10",
			"type": "cuisines",
			"attributes": {
				"name": "นานาชาติ",
				"name_en": "International",
				"name_th": "นานาชาติ",
				"total_restaurants": 311,
				"cover": {
					"url": "https://hhstaging.hungryhub.com/uploads/restaurant_tag/cover/10/cuisine-international.jpeg",
					"thumb_url": "https://hhstaging.hungryhub.com/uploads/restaurant_tag/cover/10/cuisine-international.jpeg"
				}
			}
		},
		{
			"id": "14",
			"type": "cuisines",
			"attributes": {
				"name": "ก๋วยเตี๋ยว",
				"name_en": "Noodle",
				"name_th": "ก๋วยเตี๋ยว",
				"total_restaurants": 311,
				"cover": {
					"url": "https://hhstaging.hungryhub.com/img/hh_logo.png",
					"thumb_url": "https://hhstaging.hungryhub.com/img/hh_logo.png"
				}
			}
		},
......

We need to store both EN and TH Android:

ArrayList<String> cuisineId = new ArrayList<String>();
cuisineId.add("14");
cuisineId.add("225");
cleverTap.setMultiValuesForKey("cuisine_id", cuisineId);

ArrayList<String> cuisineName = new ArrayList<String>();
cuisineName.add("Chinese");
cuisineName.add("Japanese");
cleverTap.setMultiValuesForKey("cuisine_name_en", cuisineName);

ArrayList<String> cuisineName = new ArrayList<String>();
cuisineName.add("ก๋วยเตี๋ยว");
cuisineName.add("นานาชาติ");
cleverTap.setMultiValuesForKey("cuisine_name_th", cuisineName);

iOS:

CleverTap.sharedInstance()?.profileSetMultiValues(["14", "225"], forKey: "cuisine_id")

CleverTap.sharedInstance()?.profileSetMultiValues(["Chinese", "Japanese"], forKey: "cuisine_name_en")

CleverTap.sharedInstance()?.profileSetMultiValues(["ก๋วยเตี๋ยว", "นานาชาติ"], forKey: "cuisine_name_th")

Add the used promo code in Charge Event We have used_vouchers data in booking response, we'll put that in Charged event on clevertap like this: Android:

....
chargedEvent.put("used_vouchers", "AISUDN98Q2,MOTHERDAYS");
.....

iOS:

.....
params["used_vouchers"] = "AISUDN98Q2,MOTHERDAYS"
.....

I check on TrackingManager.swift line 334

Restaurant Review

Trigger when click "Rate" on first step review. Event Name: Restaurant Reviewed Properties:

ParameterExample ValueNote
restaurant_id837restaurant id
reservation_id567890reservation id
restaurant_nameCopperrestaurant name
reviewGood restaurantfrom text review
rating5from total star

Trigger when click "submit review" on the full review Event Name: Restaurant Complete Reviewed Properties:

ParameterExample ValueNote
restaurant_id837
reservation_id567890
restaurant_nameCopper
reviewgood resto
rating5
food5
ambience5
service5
value5
occasion_nameDate
total_photos3

Store User's language to User Properties

Store User's last booking as part of User Properties. We will update language property when user sign in or changes language from profile. Example response from sign-in: Trigger:

  • user sign in
  • user sign up
  • change language

Android

HashMap<String, Object> profileUpdate = new HashMap<String, Object>();
profileUpdate.put("language", "en");

cleverTap.pushProfile(profileUpdate);

iOS

let profile: Dictionary<String, AnyObject> = [
    "language": "en"]

CleverTap.sharedInstance()?.profilePush(profile)

Store 5 last viewed restaurants to User Properties

Store last viewed restaurant in local, and update array id to clevertap properties with key last_viewed_restaurant_id Android:

cleverTap.setMultiValuesForKey("last_viewed_restaurant_id", resIds);

iOS:

CleverTap.sharedInstance()?.profileSetMultiValues(["14", "225"], forKey: "last_viewed_restaurant_id")

Reference: https://developer.clevertap.com/docs/concepts-user-profiles#manually-updating-single-value-user-profile-properties

Add Event Gift Card Purchase

Trigger when successful purchase giftcard Event Name: "Gift Card Purchased" Properties:

ParameterExample ValueNote
total_value1000from attribute total_price
platformWebWeb/iOS/Android
registeredGuestGuest/User

Loyalty Program User's Properties

From clevertap campaign we need to track how many booking or how munch money to spend to reach next level. Instead calculate on each platform need 3 people to work, better calculate from backend and client send the data to clevertap properties:

  1. booking_to_next_tier
  2. spend_to_next_tier We have 2 scenario for this:
  3. Standar Qualification
  4. Regain Level (if the previous level is higher than current) If standar will use this logic: qualification.total_reservations (from loyalty) - total_reservations (from profile) qualification.total_spend (from loyalty) - total_spend (from profile)

if regain will use this logic: regain.total_reservations (from loyalty) - progress_total_reservations (from profile) regain.total_spend (from loyalty) - progress_total_spend (from profile)

Add Event Point Earned

This one trigger when the users get points, either from reservation or give reviews.

Add Event Point Used

This one trigger when the users use point on the reservations.

Set user's properties for number booking and spend to next tier

Trigger when user see profile page (after get profile data) Android

HashMap<String, Object> profileUpdate = new HashMap<String, Object>();
profileUpdate.put("number_booking_to_next_tier", 2);
profileUpdate.put("total_spend_to_next_tier", 5000);

cleverTap.pushProfile(profileUpdate);

iOS

let profile: Dictionary<String, AnyObject> = [
    "number_booking_to_next_tier": 2,
    "total_spend_to_next_tier": 5000
]

CleverTap.sharedInstance()?.profilePush(profile)

Reference: https://developer.clevertap.com/docs/concepts-user-profiles#manually-updating-single-value-user-profile-properties

Set user's properties for average spend and total package reservation

Trigger when user see profile page (after get profile data) Android

HashMap<String, Object> profile update = new HashMap<String, Object>();
.....
profileUpdate.put("avg_spend_per_person", 6445);
profileUpdate.put("avg_pax_per_booking", 5);
profileUpdate.put("total_ayce_reservation", 23);
profileUpdate.put("total_pp_reservation", 5);
profileUpdate.put("total_xp_reservation", 2);

cleverTap.pushProfile(profileUpdate);

iOS

let profile: Dictionary<String, AnyObject> = [
    .....
    "avg_spend_per_person": 6445,
    "avg_pax_per_booking": 5,
    "total_ayce_reservation": 23,
    "total_pp_reservation": 5,
    "total_xp_reservation": 2
]

CleverTap.sharedInstance()?.profilePush(profile)

Update 30 January 2024

Store all clevertap_props to user properties

Based on this slack discussion we'll put all clevertap_props to clevertap user properties. Everytime we hit get profile we'll have this data:

"clevertap_props": {
			"Email": "tioo@yahoo.com",
			"Name": "tio",
			"Phone": "+6282198472226",
			"Identity": "188686",
			"provider": "hungryhub",
			"photo": "https://hh-engineering.sgp1.digitaloceanspaces.com/assets/fallback_avatars/default-43f3008b9022d3987b7eab0f71ec2ba434b3b78fb89959454d33ed04a3c29cd7.jpg",
			"credits": 6326,
			"all_reservations_count": 101,
			"active_reservations_count": 46,
			"no_show_reservations_count": 0,
			"cancel_reservations_count": 43,
			"language": "en",
			"age": 0,
			"total_booking": 46,
			"total_spending": 0,
			"early": 1,
			"subscribe_transaction_email": true,
			"subscribe_marketing_email": true,
			"top_loyalty_level_id": 4,
			"top_loyalty_level": "Platinum",
			"last_loyalty_level_id": 3,
			"last_loyalty_level": "Gold",
			"current_loyalty_level_id": 4,
			"current_loyalty_level": "Platinum",
			"current_loyalty_level_expiry_date": "22/05/2024",
			"ny23_qualification": "no"
		}

Android

HashMap<String, Object> profile update = new HashMap<String, Object>();
.....
profileUpdate.put("Email", "tioo@yahoo.com");
profileUpdate.put("Name", "tio");
profileUpdate.put("Phone", "+6282198472226");
profileUpdate.put("Identity", "188686");
........

cleverTap.pushProfile(profileUpdate);

iOS

let profile: Dictionary<String, AnyObject> = [
    .....
    "Email", "tioo@yahoo.com",
    "Name", "tio",
    "Phone", "+6282198472226",
    "Identity", "188686",
    .....
]

CleverTap.sharedInstance()?.profilePush(profile)

Notes: if subscribe_marketing_email is missing or user skip subscribe marketing email, the default value is false. And we need to add this parameter also: Android:

profileUpdate.put("MSG-email", false);

iOS:

...
"MSG-email", false,
...

Those params will update email subscriptions false on this communication preference:

Backend Task Backend also need to update MSG-email false when user register without subscribe marketing email and also when skip marketing email from admin. https://developer.clevertap.com/docs/upload-user-profiles-api