Enable product view signals in an Android app

The product view signal captures when a user views a product detail screen — for example, a product detail page or bottom sheet in retail, an itinerary or room view in travel, or a specific policy or account page in financial services. It helps your marketing team understand which products receive the most attention and enables segmentation by product and product category in Connect.

Availability: Premium and Ultimate

Languages: Kotlin and Java


Implementation considerations

When to fire the signal

Fire the product view signal each time a product detail screen or bottom sheet loads. Use productView instead of pageView on product detail screens — productView carries the richer schema and is the semantically correct signal type for this context.

If your app shows multiple products simultaneously — for example, a shortlist of hotel rooms — fire one signal per product.

Product catalog

The product view signal automatically updates your product catalog in Connect:

  • If the product ID is new, Connect creates a catalog entry from the signal data.
  • If the product ID already exists, Connect updates the following catalog attributes from the signal: productName, unitPrice, productCategory, productDescription, currency, discount, availability, brandName, imageUrls, inventoryQuantity, model, msrp, productRating, productStatus, productUrls, and sku.
  • Connect matches categories by the productCategory string — if a category with that name already exists, the signal maps to it; if it's new, Connect creates a catalog category entry and assigns it an internal ID.

Null values do not overwrite existing catalog data. Empty strings update the field to blank. Zero values update numeric fields to zero.

Relationship to the product configuration signal

The product view and product configuration signals work together:

  • productView — captures the product itself when the screen loads
  • productConfiguration — captures user interactions on the product screen, such as selecting a color or size

Contact mapping

Use the audience field to map the signal to a contact in Connect. Commonly used identifiers are email address, phone number, and customer ID.

📘

Note

A customer ID mapped to the Contact key attribute in Connect is the most reliable identifier for known contacts. However, if no matching contact exists and the only attribute is a contact key, the signal is discarded — contact keys alone cannot create new contacts.

Sources of the identifier in an Android app:

  • In-memory session object (for example, UserSession.email)
  • SharedPreferences for persisted login state
  • Room database or other local store

The value must be a JSONObject where each key is a contact attribute name as it appears in Connect (including capitalization and spacing) and each value is the attribute value. For phone number attributes, use the E.164 format: +[country code][area code][phone number] — no spaces, dashes, or special characters. If the + symbol is omitted, Connect adds it automatically.

📘

Note

We recommend attaching identifiers to as many signals as possible. If the user is not authenticated, omit audience — Connect will attempt to identify the visitor using other signals from the same session.


Configuration

Method

Connect.logSignal(data: HashMap<String?, Any?>?): Boolean

Sends the signal to the Acoustic Connect endpoint. The Connect SDK must be initialized via Connect.enable() before calling this method.

Pass all fields as a flat HashMap. The SDK handles the signal structure automatically — you do not need to construct a nested object.

Signal fields

Required

FieldSchema typeDescription
productIdStringUnique product identifier (may match SKU)
productNameStringName of the product
signalTypeStringSignal type. Value: "productView".

Optional

FieldSchema typeDescription
audienceJSONObjectKey-value pairs for contact mapping. Must be a flat JSONObject — not a HashMap. Keys must match contact attribute names exactly as they appear in Connect.
availabilityStringAvailability status (for example, "In Stock", "Out of Stock", "Back Order")
brandNameStringBrand name of the product
categoryStringSignal category. Value: "Behavior".
currencyStringISO 4217 currency code (for example, "USD", "EUR"). Defaults to the currency set for your Connect subscription.
descriptionStringA description of the signal
discountNumberDiscount amount or difference between original and current price. Pass as a string.
effectStringDescribes the effect of the signal on engagement. Use "positive" for product views.
imageUrlsJSONArrayURLs of product images. Pass as a JSONArray of strings.
inventoryQuantityNumberNumber of units available. Pass as a string.
modelStringModel number or description
msrpNumberSuggested retail price or original price. Pass as a string.
nameStringA label to differentiate this signal from others (for example, "productView from Android app"). Max 256 characters
productCategoryStringProduct category from your catalog
productDescriptionStringDescription of the product
productRatingNumberRating of the product. Pass as a string.
productStatusStringCurrent lifecycle state (for example, "Active", "Discontinued", "Upcoming")
productUrlsJSONArrayURLs of product pages. Pass as a JSONArray of strings.
promotionIdStringID from a marketing campaign that led to this view
shoppingCartUrlStringURL or deep link to the shopping cart
skuStringSKU, if different from productId
unitPriceNumberUnit price of the product. Pass as a string.
virtualCategoryStringCategory based on navigation path (for example, "New arrivals", "Sale")

Things to know

  • Fields with schema type Number must be passed as strings. The SDK serializer silently drops numeric values.

  • Pass audience as a JSONObject, not a HashMap. A HashMap value is silently dropped by the SDK serializer and the contact will not be mapped.

  • Pass imageUrls and productUrls as a JSONArray of strings.

  • If a required field is missing or invalid, the entire signal is discarded. If a required field isn't applicable to your business, use a placeholder value.

Required imports

import org.json.JSONArray
import org.json.JSONObject

Basic example

val data = hashMapOf<String?, Any?>(
    "signalType" to "productView",
    "productId" to "SKU-12345",
    "productName" to "Wireless Headphones"
)
Connect.logSignal(data)

Complete example

This example fires a product view signal from a product detail bottom sheet when the screen loads. It includes pricing, category, and optional contact mapping.

import org.json.JSONObject
import com.acoustic.connect.android.connectmod.Connect

private fun sendProductViewSignal() {
    // Fields with schema type Number must be passed as strings
    val data = hashMapOf<String?, Any?>(
        "signalType" to "productView",
        "productId" to product.id,
        "productName" to product.name,
        "unitPrice" to product.price.toPlainString(),
        "productCategory" to product.category.displayName,
        "currency" to "USD",
        "effect" to "positive"
    )

    // audience must be JSONObject — HashMap values are silently dropped
    UserSession.email?.let { email ->
        data["audience"] = JSONObject().put("Email Address", email)
    }

    Connect.logSignal(data)
}

Call sendProductViewSignal() from onViewCreated(), after the product data is available.


Troubleshooting

Signal not appearing in Connect?

  • Confirm Connect.enable() is called before logSignal.
  • Check that logSignal returns true. A false return indicates the SDK rejected the call.
  • Verify the appKey and postMessageUrl match the Connect org you're checking.

Signal marked as invalid in Connect?

  • Confirm all required fields are present: signalType, productId, productName.
  • Verify that Number fields are passed as strings — use price.toPlainString().

Contact not created or updated?

  • Confirm audience is a JSONObject, not a HashMap.
  • Verify attribute key names match exactly how they appear in Connect — including capitalization and spacing.

Related pages