android-mobile-sdk

Inlines(Jetpack Compose)

Overview

Inline campaigns display via views embedded in your application's user interface. Initially, these views are hidden, however, they will still exist within the layout and their height will be 0px. When activated, they are expanded with animation to reveal the campaign. They will usually contain a headline, a message, and potentially a Call To Action (CTA).

The process to display an inline campaign is as follows:

  1. When the activity is passed into the Granify Android SDK during the Granify.trackPageView(...) call, the SDK will search through the activity and identify all the GranifyInlineComposable elements that are present on the page.
  2. When a shopper matches to a campaign, our servers tell the SDK to display an inline campaign in a specific GranifyInlineComposable on the page for the user to see.
  3. The SDK will search through the available inline views and select the GranifyInlineComposable that the campaign will display in.
  4. The inline campaign initializes itself within the location.

Implementation

To enable the Granify SDK to display inline campaigns you must add at least one GranifyInlineComposable to your app. When a campaign is selected for display, the Granify SDK will look for an appropriate GranifyInlineComposable, load and insert the code for the campaign into the view, and display it.

NOTE: In a Jetpack Compose layout, the GranifyInlineComposable class is used to add a GranifyInlineView to the layout.

Adding a GranifyInlineComposable requires the following steps, which will be elaborated on in the respective sections:

  1. Add the GranifyInlineComposable to your UI
  2. Provide a label for the GranifyInlineComposable via the initialization parameter

The following sections will go through these steps in greater detail.

Adding a GranifyInlineComposable to your UI

To support inline campaigns, you will need to add a GranifyInlineComposable to every position on a page where it is desired for an inline to appear.

LazyColumn {
    items(cartItems.intValue) { index ->
        val product = Cart.items.keys.elementAt(index)
        val quantity = Cart.items.values.elementAt(index)
        key(product.sku) {
          GranifyInlineComposable(
                GranifyInlineViewLabel(
                    "aboveCartItem",
                    product.productId,
                    product.sku
                )
            )
        }
        Card(product, quantity, context, { removeItem(product) })
    }
}

Setting the Label

GranifyInlineViewLabel identifies unique locations on a page and must not be duplicated within the same page.

The GranifyInlineViewLabel has 3 fields that make the label unique to a location on a page:

  • name: Required String
    • Identifies the associated GranifyInlineComposable. This field must be unique per location on an Activity. If an Activity containing a GranifyInlineComposable is reused for several pages only one unique label is required. The label must only be unique within a page, it can be used elsewhere within your application.
  • productId: Optional String
    • The ID of the associated product. Required when theGranifyInlineComposable is located on a product page, or on any page where the GranifyInlineComposable is associated with a specific product (e.g. inlines associated with a cart product).
  • sku: Optional String
    • This field is required when the associated GranifyInlineComposable is associated with a specific productID/sku combination. If a sku is specified, a productId must also be specified however a productId can be specified without a sku.

Multiple labels can exist on a single page and the name field will be used to uniquely identify them when the productId and sku fields are the same. For example, a product page for productId "Pants" with sku "Green" could have the following labels:

  • GranifyInlineViewLabel(name="aboveProductPhoto", productId="Pants", sku="Green")
  • GranifyInlineViewLabel(name="belowProductPhoto", productId="Pants", sku="Green")
  • GranifyInlineViewLabel(name="belowAddToCartButton", productId="Pants", sku="Green")

A GranifyInlineComposable located on a product page must (at minimum) use the name and productId parameters. The sku should also be provided where applicable.

On a cart page, a GranifyInlineComposable not associated with any product (for example at the top of the page) would only require the name field in the GranifyInlineViewLabel. However, if the GranifyInlineComposable was associated with a product in the cart, then the name and productId fields would be required. The sku field would also be required if there are multiple SKUs for that product. If these labels are not properly created, the inline display will not work properly.

A list of all GranifyInlineComposable in your application must be sent to your Granify Project Manager / Account Manager for us to create inline campaigns.

Do not change these label names without prior warning as this will break live campaigns.

Testing your GranifyInlineComposable

Because a GranifyInlineComposable is embedded into your user interface they must be tested extensively to make sure that expanding and collapsing them does not interfere with any of your other layouts.

To specify which location to attach an inline to while testing, the method Granify.overrideGranifyInlineView(label: String?) has been provided within the SDK. This method should be used exclusively during testing and allows for specifying a list of GranifyInlineViewLabel (in JSON) that will override the locations that Granify will use to display our inline campaigns. Also note that this list is ordered by priority and the first label within a page that matches in the list will be used for display.

If you would like to reset to the default behaviour of having Granify select the inline location, call Granify.overrideGranifyInlineView(label: String?) method with the label parameter set to null.

The label parameter of this method is a string of JSON which correlates to the GranifyInlineViewLabel fields in the format: "[{\"name\": \"LABEL_NAME\", \"product_id\": \"PRODUCT_ID\", \"sku\": \"PRODUCT_SKU\"}]"

Note that the JSON string here has three catches that can make troubleshooting difficult:

  • The product_id field in the JSON is all lowercase and contains an underscore while the productId field in the GranifyInlineViewLabel is camel case and does not contain any special characters.
  • The JSON string is an array of labels rather than just a single label to allow for specifying multiple inline locations that can be attached to when testing.
  • The product_id and sku fields can be set to null to act as a wildcard match to any GranifyInlineViewLabel that matches the name field. If just the sku field is set to null then any GranifyInlineViewLabels that match both the name and productId fields will be chosen for display.

Example Usage Scenario

Three new GranifyInlineComposable locations were added to a product page layout and a developer would like to test them to ensure they behave as expected. The developer will go through the following steps:

  1. Translate the GranifyInlineViewLabel that was set for each location into JSON. If the new labels were:
    GranifyInlineViewLabel(name="aboveProductPhoto", productId="Pants", sku="Green")
    GranifyInlineViewLabel(name="belowProductPhoto", productId="Pants", sku="Green")
    GranifyInlineViewLabel(name="belowAddToCartButton", productId="Pants", sku="Green")
    If you are targeting a location on a specific product/SKU, the product information needs to be included. From the GranifyInlineViewLabel above, they would translate to the following JSON for testing:
    {"name": "aboveProductPhoto", "product_id": "Pants", "sku": "Green"}
    {"name": "belowProductPhoto", "product_id": "Pants", "sku": "Green"}
    {"name": "belowAddToCartButton", "product_id": "Pants", "sku": "Green"}
    If the location is not product or SKU specific, the product details may be omitted from their respective fields. In this example, since both the product_id and sku fields were set to null, Granify will automatically match any GranifyInlineViewLabel that shares the same name field regardless of product.
    {"name": "aboveProductPhoto", "product_id": null, "sku": null}
    {"name": "belowProductPhoto", "product_id": null, "sku": null}
    {"name": "belowAddToCartButton", "product_id": null, "sku": null}
    Note: The sku field can also be omitted independently of the product_id field if testing a GranifyInlineViewLabel for a specific product where the SKU does not matter. However, product_id cannot be omitted if a sku is provided.
  2. Add the JSON for each field into an array so that it will then appear as:
    [
        {"name": "aboveProductPhoto", "product_id": null, "sku": null},
        {"name": "belowProductPhoto", "product_id": null, "sku": null},
        {"name": "belowAddToCartButton", "product_id": null, "sku": null}
    ]
  3. Ensure that the JSON array can be translated into a string. Shown here is the array after escaping the quote characters and removing the newlines being assigned as the value to overrideLabelString as well as an unescaped string example for use within the method call in the next step.
    val overrideLabelString: String = "[{\"name\":\"aboveProductPhoto\",\"product_id\":null,\"sku\":null},{\"name\":\"belowProductPhoto\",\"product_id\":null,\"sku\":null},{\"name\":\"belowAddToCartButton\",\"product_id\":null,\"sku\": null}]"
    // If unescaped JSON is preferable then the following also works
    val overrideLabelString: String = """
      [
          {"name": "aboveProductPhoto", "product_id": null, "sku": null},
          {"name": "belowProductPhoto", "product_id": null, "sku": null},
          {"name": "belowAddToCartButton", "product_id": null, "sku": null}
      ]
    """
  4. Call the Granify.overrideGranifyInlineView(label: String?) method with the JSON string as the label parameter.
  5. Force match to an inline campaign (this will be provided by Granify to you during your installation) and navigate to the page to which the new inline locations have been added to.
  6. Observe as the campaign displays in the first label that was provided in the array, in this scenario this is a GranifyInlineComposable with the name field set to "aboveProductPhoto"

We recommend having a text box in a debug menu that calls Granify.overrideGranifyInlineView(label: String?) when the JSON object is input. Using this override makes any matched inline campaign appear in the GranifyInlineComposable with one of the GranifyInlineViewLabel that has been specified.

Inlines and Restricted States

Please note that inline campaigns are not affected by restricted states. They will not be hidden while in a restricted state.

See Granify.setRestrictionState(state: RestrictionState) for more information on how and when restriction states are set.