Retrieve Membership-Offers

Retrieve Membership-Offers Tutorial

Learn how to retrieve and present only those offers that are relevant to a member.

Intro

A successful marketing program may consist of offers with a wide variety of configurations; some are meant to engender general engagement with the program and are available to all members, but others may be targeted to a specific group of members based on their behavioral or demographic characteristics. Offers may also require certain actions, like Activation, or be constrained by fulfillment limits.

A marketing program is most effective when it is able to target a member with offers specific to their needs, and is most helpful to a member when it can display only those offers that they're able to engage with. It is misleading, for instance, to display an offer that a member may not fulfill because they do not belong to a required custom segment, or because the offer has already met a global Limit; by displaying such an offer a member may incorrectly expect to engage with it and thus earn an award, and may become disappointed with or mistrustful of the program when they do not.

The Membership-Offers displays only the offers that belong to the same Chain as the member, but will default to including offers that are discontinued, unpublished, or limited -- as well as those offers that are available for immediate engagement. Further, some offers may require additional prerequisite actions to be taken before they may be fulfilled.

In this tutorial, you'll learn how to customize a call to the Membership-Offers api in order to retrieve only those relevant offers, and to use the other attributes of the offer in order to inform a user about additional requirements. You'll also learn how to include the marketing contents for each offer, and cut down on payload size with sparse fields.

This tutorial walks through the following set of steps:

  1. Membership-Offers API
  2. Visibility Filtering
  3. Eligibility
  4. Activation Status
  5. Include Marketing Contents
  6. Use sparse fieldsets

Steps

Step 1: Membership-Offers API

While the Offers api may be used to retrieve all of the available offers in your marketing program, it's most effective to show a membership their offers. This can be done by calling the Membership-Offers api:

Membership-Offers Retrieval - Example Request

curl -X GET \
  https://api.hatchloyalty.com/api/v2/memberships/354067ec-ff43-487b-91ed-9134ac79954d/offers \
  -H 'accept: application/vnd.api+json' \
  -H 'authorization: Bearer 066a7466'

Membership-Offers Retrieval - Example Response

{
  "data": [
    {
      "id": "5276b1a0-6dc1-445f-8a31-7e1ce794fcfa",
      "type": "offers",
      "links": {
        "self": "https://api.hatchloyalty.com/api/v2/memberships/354067ec-ff43-487b-91ed-9134ac79954d/offers"
      },
      "attributes": {
        "chain_id": "9b7575cb-a1ff-405f-9390-4ea826666c5f",
        "external_id": null,
        "name": "100 mega-point hover-bike recharge",
        "description": "We have plans to add hover-bike recharging stations in the future; this offer launches in the fall of 2050.",
        "category": "transactional",
        "must_activate": false,
        "created_at": "2017-07-19T14:42:42.165Z",
        "publish_at": "2050-08-15T07:00:00.000Z",
        "expire_at": "2052-08-29T22:00:00.000Z",
        "custom_data": {},
        "discontinued": false,
        "activated": null,
        "eligible": false,
        "fulfillment_count": 0,
        "activation_status": "does_not_require_activation",
        "visible_status": "unpublished",
        "rule_id": "b13418a6-282d-4607-aa5c-2950cac52436"
      }
    },
    // Many additional offers
  ],
  "meta": {
    "record_count": 500
  },
  "links": {
    "first": "https://api.hatchloyalty.com/api/v2/memberships/354067ec-ff43-487b-91ed-9134ac79954d/offers?page%5Bcursor%5D=1&page%5Bsize%5D=20",
    "next": "https://api.hatchloyalty.com/api/v2/memberships/354067ec-ff43-487b-91ed-9134ac79954d/offers?page%5Bcursor%5D=1556140382.000000&page%5Bsize%5D=20"
  }
}

Note: the visible_status of this offer indicates that that this offer is unpublished. Based on the publish_at field, it seems that this offer won't be available until the year 2050, so it might not make sense to show this offer to the member until then. Your client code could filter out these offers before displaying them, but it might traverse the entire page of results only to find one or two that are relevant to this member. If these offers are being displayed in a mobile application, you will have to make additional requests that contain irrelevant offers, also causing your application to load more slowly.

Instead, make use of filters to select only the offers that are relevant to this member.

Step 2: Visibility Filtering

As above, offers contain a field called visible_status that can be used to select only relevant offers. Reading more on Visibility shows that a visible_status of visible will indicate offers that are ready to be shown to the member. We can filter on this field by including the filter[visible_status]=visible query parameter.

Visible Membership-Offers Retrieval - Example Request

curl -X GET \
  https://api.hatchloyalty.com/api/v2/memberships/354067ec-ff43-487b-91ed-9134ac79954d/offers?&filter[visible_status]=visible \
  -H 'accept: application/vnd.api+json' \
  -H 'authorization: Bearer 066a7466'

Visible Membership-Offers Retrieval - Example Response

{
  "data": [
    {
      "id": "bc9fcc89-6a99-4bc4-852b-f9bd52b0f195",
      "type": "offers",
      "links": {
        "self": "https://api.hatchloyalty.com/api/v2/memberships/354067ec-ff43-487b-91ed-9134ac79954d/offers"
      },
      "attributes": {
        "chain_id": "9b7575cb-a1ff-405f-9390-4ea826666c5f",
        "external_id": null,
        "name": "2 oranges for 100 points. Requires activation.",
        "description": "Orange producer would like members to show intent; this offer requires activation.",
        "category": "transactional",
        "must_activate": true,
        "created_at": "2017-07-19T14:42:42.165Z",
        "publish_at": "2050-08-15T07:00:00.000Z",
        "expire_at": "2052-08-29T22:00:00.000Z",
        "custom_data": {},
        "discontinued": false,
        "activated": false,
        "eligible": false,
        "fulfillment_count": 0,
        "activation_status": "requires_activation",
        "visible_status": "visible",
        "rule_id": "579807c5-de8f-4aca-a49a-1b3c4909179f"
      }
    },
    // Some additional offers
  ],
  "meta": {
    "record_count": 12
  },
  "links": {
    "first": "https://api.hatchloyalty.com/api/v2/memberships/354067ec-ff43-487b-91ed-9134ac79954d/offers?page%5Bcursor%5D=1&page%5Bsize%5D=20",
    "next": "https://api.hatchloyalty.com/api/v2/memberships/354067ec-ff43-487b-91ed-9134ac79954d/offers?page%5Bcursor%5D=1556140382.000000&page%5Bsize%5D=20"
  }
}

We see by the meta key's record_count value of 12 compared to the previous requests 500 that many fewer offers have now been retrieved.

An effective marketing campaign contains some offers that all members may engage with (e.g., receiving a small number of points for each dollar spent), but many that are specifically targeted to members based on their Audiences. All of the offers retrieved in this way may be shown immediately to the member because they are all calculated to be relevant.

Note: this offer still indicates that it is eligible: false. We may want to deal with these offers explicitly by providing specific information to the member as to what they must do in order to be eligible for this offer.

Step 3: Eligibility

Offers that are ineligible but otherwise visible are not available for a member to immediately engage with, and require certain prerequisite actions from the member. The Eligibility documentation describes the such actions, such as Activation.

Note: Activation is currently the only prerequisite action supported by Hatch, but others may be available in the future. For this reason, it's not helpful to simply filter out all of the ineligible offers -- but instead to inspect the other properties of the offer in order to indicate the desired action.

In this case, activation_status indicates that this offer requires_activation. It would be helpful to place a banner or button near the offer to allow the member to "claim" or Activate it. Once done, this offer will indicate that it is eligible: true with an activation_status: activated; the member knows that it has been activated and that they are free to engage with it.

Step 4: Activation Status

Although it's not helpful to filter-out ineligible offers, there may be cases where it's desirable to show only offers that depend on activation. The Activation documentation shows that we could power a "My activated offers" view with the activation_status activated value, or a "Unclaimed offers" section with the requires_activation value. Highlighting these types of offers may further encourage the member to engage with the appropriate prerequisite behavior.

Similar to visible_status, we can filter for those types of offers explicitly (keeping in mind to include the earlier filter[visible_status]=visible) with filter[activation_status], either for activated or requires_activation.

Activated Membership-Offers Retrieval - Example Request

curl -X GET \
  https://api.hatchloyalty.com/api/v2/memberships/354067ec-ff43-487b-91ed-9134ac79954d/offers?&filter[visible_status]=visible&filter[activation_status]=activated \
  -H 'accept: application/vnd.api+json' \
  -H 'authorization: Bearer 066a7466'

Unactivated Membership-Offers Retrieval - Example Request

curl -X GET \
  https://api.hatchloyalty.com/api/v2/memberships/354067ec-ff43-487b-91ed-9134ac79954d/offers?&filter[visible_status]=visible&filter[activation_status]=requires_activation \
  -H 'accept: application/vnd.api+json' \
  -H 'authorization: Bearer 066a7466'

The responses are omitted for brevity, but will look similar to other Offer responses -- except that all of the offers will be of the specified activation_status and will be visible to the member.

Step 5: Include Marketing Contents

The name and description fields of an offer are meant for internal reference and should not be displayed in consumer-facing messaging. Instead, make use of an offer's associated Marketing Contents to specify locale-specific consumer copy. These marketing contents can be eagerly loaded with the Membership-Offer request in order to cut-down on the total number of requests necessary to retrieve all of the information necessary to display targeted offers to a member.

Visible Membership-Offers with Marketing Contents Retrieval - Example Request

curl -X GET \
  https://api.hatchloyalty.com/api/v2/memberships/354067ec-ff43-487b-91ed-9134ac79954d/offers?&filter[visible_status]=visible&include=marketing_contents \
  -H 'accept: application/vnd.api+json' \
  -H 'authorization: Bearer 066a7466'

Visible Membership-Offers with Marketing Contents Retrieval - Example Response

{
  "data": [
    {
      "id": "bc9fcc89-6a99-4bc4-852b-f9bd52b0f195",
      "type": "offers",
      "links": {
        "self": "https://api.hatchloyalty.com/api/v2/memberships/354067ec-ff43-487b-91ed-9134ac79954d/offers"
      },
      "attributes": {
        "chain_id": "9b7575cb-a1ff-405f-9390-4ea826666c5f",
        "external_id": null,
        "name": "2 oranges for 100 points. Requires activation.",
        "description": "Orange producer would like members to show intent; this offer requires activation.",
        "category": "transactional",
        "must_activate": true,
        "created_at": "2017-07-19T14:42:42.165Z",
        "publish_at": "2050-08-15T07:00:00.000Z",
        "expire_at": "2052-08-29T22:00:00.000Z",
        "custom_data": {},
        "discontinued": false,
        "activated": false,
        "eligible": false,
        "fulfillment_count": 0,
        "activation_status": "requires_activation",
        "visible_status": "visible",
        "rule_id": "579807c5-de8f-4aca-a49a-1b3c4909179f"
      },
      "relationships": {
        "marketing_contents": {
          "links": {
            "self": "https://api.hatchloyalty.com/api/v2/offers/50f07c49-2b6a-4cf7-bdf4-770b3d41f221/relationships/marketing_contents",
            "related": "https://api.hatchloyalty.com/api/v2/offers/50f07c49-2b6a-4cf7-bdf4-770b3d41f221/marketing_contents"
          },
          "data": [
            {
              "type": "marketing_contents",
              "id": "5205bed5-1a4b-425c-90cc-0cea82d0bbaa"
            }
          ]
        }
      }
    },
    // Some additional offers
  ],
  "included": [
    {
      "id": "5205bed5-1a4b-425c-90cc-0cea82d0bbaa",
      "type": "marketing_contents",
      "links": {
        "self": "https://api.hatchloyalty.com/api/v2/marketing_contents/5205bed5-1a4b-425c-90cc-0cea82d0bbaa"
      },
      "attributes": {
        "created_at": "2019-04-02T17:55:29.514Z",
        "discontinued": false,
        "locale": "us_EN",
        "title": "Buy 2 oranges and receive 100 points!",
        "terms": null,
        "terms_url": null,
        "image_url": "https://images.hatchloyalty.com/oranges.jpg",
        "disclaimer_url": null,
        "short_description": "Eat healthy and get that gleam back in your eye by eating more oranges -- and get rewarded, too!",
        "long_description": "",
        "disclaimer": ""
      },
      "relationships": {
        "subject": {
          "links": {
            "self": "https://api.hatchloyalty.com/api/v2/marketing_contents/5205bed5-1a4b-425c-90cc-0cea82d0bbaa/relationships/subject",
            "related": "https://api.hatchloyalty.com/api/v2/marketing_contents/5205bed5-1a4b-425c-90cc-0cea82d0bbaa/subject"
          }
        }
      }
    },
  ],
  "meta": {
    "record_count": 12
  },
  "links": {
    "first": "https://api.hatchloyalty.com/api/v2/memberships/354067ec-ff43-487b-91ed-9134ac79954d/offers?page%5Bcursor%5D=1&page%5Bsize%5D=20",
    "next": "https://api.hatchloyalty.com/api/v2/memberships/354067ec-ff43-487b-91ed-9134ac79954d/offers?page%5Bcursor%5D=1556140382.000000&page%5Bsize%5D=20"
  }
}

By matching the offer's marketing content (from the offer's relationships field) to the included marketing contents by id, the client application can display locale-specific marketing copy, disclaimers, and images to the member.

Step 6: Use sparse fieldsets

You've now crafted an api request to return just the offers that a member cares about -- along with the marketing content information to display them. This is great, but the responses are still a little large and contain some extra information that we may not care to display (e.g., the offer's name, or the marketing content's long_description). Make use of Sparse Fieldsets to only retrieve the information that needs to be shown.

Visible Membership-Offers with Marketing Contents and Sparse Fieldsets Retrieval - Example Request

curl -X GET \
  https://api.hatchloyalty.com/api/v2/memberships/354067ec-ff43-487b-91ed-9134ac79954d/offers?&filter[visible_status]=visible&include=marketing_contents&fields[offers]=id,activation_status,eligible,marketing_contents&fields[marketing_contents]=image_url,title,short_description \
  -H 'accept: application/vnd.api+json' \
  -H 'authorization: Bearer 066a7466'

Visible Membership-Offers with Marketing Contents and Sparse Fieldsets Retrieval - Example Response

{
  "data": [
    {
      "id": "bc9fcc89-6a99-4bc4-852b-f9bd52b0f195",
      "type": "offers",
      "links": {
        "self": "https://api.hatchloyalty.com/api/v2/memberships/354067ec-ff43-487b-91ed-9134ac79954d/offers"
      },
      "attributes": {
        "eligible": false,
        "activation_status": "requires_activation",
      },
      "relationships": {
        "marketing_contents": {
          "links": {
            "self": "https://api.hatchloyalty.com/api/v2/offers/50f07c49-2b6a-4cf7-bdf4-770b3d41f221/relationships/marketing_contents",
            "related": "https://api.hatchloyalty.com/api/v2/offers/50f07c49-2b6a-4cf7-bdf4-770b3d41f221/marketing_contents"
          },
          "data": [
            {
              "type": "marketing_contents",
              "id": "5205bed5-1a4b-425c-90cc-0cea82d0bbaa"
            }
          ]
        }
      }
    },
    // Some additional offers
  ],
  "included": [
    {
      "id": "5205bed5-1a4b-425c-90cc-0cea82d0bbaa",
      "type": "marketing_contents",
      "links": {
        "self": "https://api.hatchloyalty.com/api/v2/marketing_contents/5205bed5-1a4b-425c-90cc-0cea82d0bbaa"
      },
      "attributes": {
        "title": "Buy 2 oranges and receive 100 points!",
        "image_url": "https://images.hatchloyalty.com/oranges.jpg",
        "short_description": "Eat healthy and get that gleam back in your eye by eating more oranges -- and get rewarded, too!"
      },
    },
  ],
  "meta": {
    "record_count": 12
  },
  "links": {
    "first": "https://api.hatchloyalty.com/api/v2/memberships/354067ec-ff43-487b-91ed-9134ac79954d/offers?page%5Bcursor%5D=1&page%5Bsize%5D=20",
    "next": "https://api.hatchloyalty.com/api/v2/memberships/354067ec-ff43-487b-91ed-9134ac79954d/offers?page%5Bcursor%5D=1556140382.000000&page%5Bsize%5D=20"
  }
}

Note that we don't need to include visible_status in the sparse fieldset because our filtering already assures us that it will be visible.

Conclusion

This sequence of steps describes the process necessary to fetch relevant offers for a member, and to use the eligible and activation_status fields to indicate the actions that are required to engage with each offer. It also describes filtering on activation_status for special views, and how to reduce request overhead by eagerly-loading marketing_contents and reduce payload size with sparse fieldsets.

These tools are indispensable when engaging a member with the offers they care about, and help ensure that they'll engage with your loyalty program.

While this is a critical aspect of your loyalty program, it is just one piece of the overall puzzle and it's important to consider the complete, end-to-end member experience when designing and refining your program. The following are a few of the other important aspects to keep in mind: