Using SPM on Mobile

You can use Sailthru's Site Personalization Manager (SPM) to send personalized content to your users across channels - Onsite, Email and Mobile.

On mobile this is dead simple, and similar to implementing our JavaScript Client Library in Custom Mode.

This guide assumes that you've set up SPM on the web, and linked your Sailthru Client with your Sailthru Mobile App.

Tracking Content Metrics

Content Metrics overview

When providing personalized content, tracking a user's interests is of great importance. Interest tracking allows you to recommend items or articles to the user that they actually care about, making them more likely to convert through your recommended content. SPM provides three different types of tracking metrics:

  • A pageview is an indication that a user has seen a given item of content's detail view - for example, a page for a certain product in an online store, or a full news article in a news site.
  • An impression is a reasonable assumption that a user has seen a given piece of content - maybe they've scrolled past it in a list view, or seen it in a "Recommended" panel on another content item.
  • A click is exactly what it sounds like: it means that a user has clicked - or in this case tapped - on a given piece of content to learn more. This usually, but not always, means that a user will now transition to that content's detail view.

Implementing Content Metrics

Tracking Pageviews

Sailthru's trackPageview method should be passed a URL corresponding to the web URL of the content being viewed, as well as an array of tags. If the tags array is empty or null, Sailthru will use any tags for this page stored in your content library - otherwise, those stored tags will be overridden by any passed to trackPageview.

NSArray<NSString*> *tags = @[@"blazer", @"beige", @"tan"];
NSURL *contentUrl = [NSURL URLWithString:@"https://varickandvandam.com/products/1153128"];

[[SailthruMobile new] trackPageviewWithUrl: contentUrl, andTags: tags, andResponse: ^(NSError *error) {
  if (error) {
        // Handle error case
  } else {
    // Things went right, hooray!
  }
}];

// Alternatively, if we don't mind too much if the track request fails, use a nil block:
[[SailthruMobile new] trackPageviewWithUrl: contentUrl, andTags: tags, andResponse: nil]
let tags = ["blazer", "beige", "tan"]
let contentUrl = URL(string: "https://varickandvandam.com/products/1153128")

SailthruMobile().trackPageview(withUrl: contentUrl, andTags: tags) { (errorOrNil) in
    if let error = errorOrnil {
        print(error)
        return
    }
    
    // Track success! 🙌
}

// Alternatively, if we don't mind too much if the track request fails, just omit the block:
SailthruMobile().trackPageview(withUrl: contentUrl, andTags: tags)
ArrayList<String> tags = new ArrayList(Arrays.asList("blazer", "beige", "tan"));
URI contentUrl = URI.create("https://varickandvandam.com/products/1153128");

new SailthruMobile().trackPageview(contentUrl, tags, new SailthruMobile.TrackHandler() {
  @Override
  public void onSuccess() {
        // We're good
  }

  @Override
  public void onFailure(Error error) {
        // Handle errors here
  }
});

// Alternatively, if we don't mind too much if the track request fails, use a null handler:
new SailthruMobile().trackPageview(contentUrl, tags, null)
val tags = listOf("blazer", "beige", "tan")
val contentUrl = URI.create("https://varickandvandam.com/products/1153128")

SailthruMobile().trackPageview(contentUrl, tags, object : SailthruMobile.TrackHandler {
    override fun onSuccess() {
        // We're good
    }

    override fun onFailure(error: Error?) {
        // Handle errors here
    }
})

// Alternatively, if we don't mind too much if the track request fails, use a null handler:
SailthruMobile().trackPageview(contentUrl, tags, null)
var url = "https://varickandvandam.com/products/1153128";
var tags = ["blazer", "beige", "tan"];

SailthruMobile.trackPageview(url, tags).then(function() {
    // handle success
}, function(error) {
    // handle error
});

// Alternatively, if we don't mind too much if the track request fails, omit then handler:
SailthruMobile.trackPageview(url, tags);

We recommend tracking pageviews as views within your app are being initialized. For example, on Android, you might call trackPageview in a Fragment's onCreateView method, whereas on iOS you might place it in a ViewController's viewDidAppear method.

Tracking Impressions

An impression should be tracked when a section of recommended content is seen by a user. Sailthru's trackImpression method takes a SPM Section ID as its first argument, and a list of URLs corresponding to the URLs of the items in the section.

NSArray<NSURL*> *urls = @[
  [NSURL URLWithString:@"https://varickandvandam.com/products/1153128"],
  [NSURL URLWithString:@"https://varickandvandam.com/products/1098230"],
  [NSURL URLWithString:@"https://varickandvandam.com/products/1078590"]
];
NSString *sectionID = @"A very real section ID";

[[SailthruMobile new] trackImpressionWithSession: sectionID, andUrls: urls, andResponse: ^(NSError *error) {
  if (error) {
        // Handle error case
  } else {
    // Things went right, hooray!
  }
}];

// Alternatively, if we don't mind too much if the track request fails, use a nil block:
[[SailthruMobile new] trackImpressionWithSession: sectionID, andUrls: urls, andResponse: nil]
let urls = [
  URL("https://varickandvandam.com/products/1153128"),
  URL("https://varickandvandam.com/products/1098230"), 
    URL("https://varickandvandam.com/products/1078590")
]
let sectionID = "a very real section ID"

SailthruMobile().trackImpression(withSection: sectionID, andUrls: urls) { (errorOrNil) in
    if let error = errorOrnil {
        print(error)
        return
    }
    
    // Track success! 🙌
}

// Alternatively, if we don't mind too much if the track request fails, just omit the block:
SailthruMobile().trackImpression(withSection: sectionID, andUrls: urls)
ArrayList<URI> urls = new ArrayList(Arrays.asList(
  URI.create("https://varickandvandam.com/products/1153128"),
  URI.create("https://varickandvandam.com/products/1098230"), 
    URI.create("https://varickandvandam.com/products/1078590")
));
String sectionID = "a very real section ID";

new SailthruMobile().trackImpression(sectionID, urls, new SailthruMobile.TrackHandler() {
  @Override
  public void onSuccess() {
        // We're good
  }

  @Override
  public void onFailure(Error error) {
        // Handle errors here
  }
});

// Alternatively, if we don't mind too much if the track request fails, use a null handler:
new SailthruMobile().trackImpression(sectionID, urls, null)
val tags = listOf(URI("https://varickandvandam.com/products/1153128"),
                  URI("https://varickandvandam.com/products/1098230"),
                  URI("https://varickandvandam.com/products/1078590"))
val sectionID = "a very real section ID"

SailthruMobile().trackImpression(sectionID, tags, object : SailthruMobile.TrackHandler {
    override fun onSuccess() {
        // We're good
    }

    override fun onFailure(error: Error?) {
        // Handle errors here
    }
})

// Alternatively, if we don't mind too much if the track request fails, use a null handler:
SailthruMobile().trackImpression(sectionID, tags, null)
var urls = ["https://varickandvandam.com/products/1153128",
            "https://varickandvandam.com/products/1098230",            
            "https://varickandvandam.com/products/1078590"]
var sectionID = "a very real section ID";

SailthruMobile.trackImpression(sectionID, urls).then(function() {
    // handle success
}, function(error) {
    // handle error
});

// Alternatively, if we don't mind too much if the track request fails, omit then handler:
SailthruMobile.trackImpression(sectionID, urls);

We recommend that you call trackImpression as a recommendation section enters the user's viewport on their device. On Android, you might do this by attaching an OnChildAttachStateChangeListener to a RecyclerView, and placing a call to trackImpression in the body of its onChildViewAttachedToWindow method. On iOS, you might consider calling trackImpression in the UITableViewDelegate method tableView:willDisplayCell.

Tracking Clicks

A click should be tracked when a user clicks on an item present in a section of recommendations, passing the section ID as the first argument, and the URL of the item being navigated to as the second argument.

NSURL *url = [NSURL URLWithString:@"https://varickandvandam.com/products/1153128"];
NSString *sectionID = @"A very real section ID";

[[SailthruMobile new] trackClickWithSession: sectionID, andUrl: url, andResponse: ^(NSError *error) {
  if (error) {
        // Handle error case
  } else {
    // Things went right, hooray!
  }
}];

// Alternatively, if we don't mind too much if the track request fails, use a nil block:
[[SailthruMobile new] trackClickWithSession: sectionID, andUrl: url, andResponse: nil]
let url = URL("https://varickandvandam.com/products/1153128")
let sectionID = "a very real section ID"

SailthruMobile().trackClick(withSection: sectionID, andUrl: url) { (errorOrNil) in
    if let error = errorOrnil {
        print(error)
        return
    }
    
    // Track success! 🙌
}

// Alternatively, if we don't mind too much if the track request fails, just omit the block:
SailthruMobile().trackClick(withSection: sectionID, andUrl: url)
URI url = URI.create("https://varickandvandam.com/products/1078590");
String sectionID = "a very real section ID";

new SailthruMobile().trackClick(sectionID, url, new SailthruMobile.TrackHandler() {
    @Override
    public void onSuccess() {
        // We're good
    }

    @Override
    public void onFailure(Error error) {
        // Handle errors here
    }
});

// Alternatively, if we don't mind too much if the track request fails, use a null handler:
new SailthruMobile().trackClick(sectionID, url, null)
val url = URI("https://varickandvandam.com/products/1078590")
val sectionID = "a very real section ID"

SailthruMobile().trackClick(sectionID, url, object : SailthruMobile.TrackHandler {
    override fun onSuccess() {
        // We're good
    }

    override fun onFailure(error: Error?) {
        // Handle errors here
    }
})

// Alternatively, if we don't mind too much if the track request fails, use a null handler:
SailthruMobile().trackClick(sectionID, url, null)
var url = "https://varickandvandam.com/products/1078590";
var sectionID = "a very real section ID";

SailthruMobile.trackClick(sectionID, url).then(function() {
    // handle success
}, function(error) {
    // handle error
});

// Alternatively, if we don't mind too much if the track request fails, omit then handler:
SailthruMobile.trackClick(sectionID, urls);

Getting Recommendations

You can request recommendations from the Site Personalization Manager based on the data that you have been supplying through the track methods. This can be used to show content that is related to items that the user has previously expressed an interest in.

🚧

JSON Recommendations

The section must use the Onsite template as json_recommendations and the variable from the rule should be set according to the chosen rule. More info can be found here.

[[SailthruMobile new] recommendationsWithSection:@"a very real section ID" withResponse:^(NSArray<STMContentItem *> * _Nullable contentItems, NSError * _Nullable error) {
  if(error) {
    // Handle errors here
    return;
  }

  // STMContentItems contain recommended item data
}];
SailthruMobile().recommendations(withSection: "a very real section ID") { ([STMContentItem]? contentItems, Error? errorOrNil) in
  if let error = errorOrNil {
    // Handle errors here
    return
  }

    // Content Items contain recommended item data
}
new SailthruMobile().getRecommendations("a very real section ID", new SailthruMobile.RecommendationsHandler() {
    @Override
    public void onSuccess(ArrayList<ContentItem> contentItems) {
        // Content Items contain recommended item data
    }

    @Override
    public void onFailure(Error error) {
        // Handle errors here
    }
});
SailthruMobile().getRecommendations("a very real section ID", object : SailthruMobile.RecommendationsHandler {
    override fun onSuccess(contentItems: ArrayList<ContentItem?>?) {
        // Content Items contain recommended item data
    }

    override fun onFailure(error: Error?) {
        // Handle errors here
    }
})
SailthruMobile.getRecommendations("a very real section ID").then(function(contentItemsArray) {
  // Content items contain recommended item data
}, function(error) {
  // Handle errors here
});

Did this page help you?