Enable product configuration signals in an Android app
The product configuration signal captures user interactions with a product that suggest evaluation and preparation to purchase — for example, selecting a colorway or adjusting quantity in retail, choosing a seat or meal preference in travel, or selecting a coverage level in financial services. It tracks engagement beyond the product view, identifying users who are actively considering a product. In Connect, the signal enables segmentation by configuration type, product, and product category.
Availability: Premium and Ultimate
Languages: Kotlin and Java
Implementation considerations
Relationship to the product view signal
The product view and product configuration signals work together:
productView— fires when the product detail screen loadsproductConfiguration— fires each time the user interacts with a product element
Use the same productId and productName values in both signals to ensure consistent tracking.
Product catalog
The product configuration 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,inventoryQuantity,imageUrls, andproductUrls. - Connect matches categories by the
productCategorystring — 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.
When to fire the signal
Fire the signal each time a user interacts with a product element on the product detail screen. Common interactions in Android apps:
- Selecting a colorway or variant chip
- Adjusting quantity
- Tapping to view additional images
- Expanding product details or reviews
For interactions that fire rapidly in sequence — such as a quantity stepper — consider debouncing to avoid sending a signal on every tap.
Configuration type labels
Use the configurationType field to identify what the user interacted with. You can label by product parameter, UI element, or action:
| Approach | Examples |
|---|---|
| Product parameter | "color", "size", "quantity", "room type" |
| UI element | "Colorway chip", "Quantity stepper", "Image thumbnail" |
| Action | "Select color", "Adjust quantity", "View image" |
Choose a consistent approach across your implementation for better analytics.
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.
NoteA 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) SharedPreferencesfor 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.
NoteWe 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?>?): BooleanSends 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
| Field | Schema type | Description |
|---|---|---|
productId | String | Unique product identifier. Use the same value as in the corresponding productView signal to keep the catalog consistent. |
productName | String | Name of the product |
signalType | String | Signal type. Value: "productConfiguration". |
Optional
| Field | Schema type | Description |
|---|---|---|
audience | JSONObject | Key-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. |
category | String | Signal category. Value: "Behavior". |
configurationType | String | Label for the interaction that occurred (for example, "color", "Select colorway") |
currency | String | ISO 4217 currency code (for example, "USD", "EUR"). Defaults to the currency set for your Connect subscription. |
description | String | A description of the signal |
discount | Number | Discount amount applied to the product. Pass as a string. |
effect | String | Describes the effect of the signal on engagement. Use "positive" for product configuration signals. |
imageUrls | JSONArray | URLs of product images. Pass as a JSONArray of strings. |
inventoryQuantity | Number | Number of units available. Pass as a string. |
name | String | A label to differentiate this signal from others (for example, "colorway selection"). Max 256 characters |
productCategory | String | Product category from your catalog |
productDescription | String | Description of the product |
productUrls | JSONArray | URLs of product pages. Pass as a JSONArray of strings. |
promotionId | String | ID from a marketing campaign that influenced this interaction |
shoppingCartUrl | String | URL or deep link to the shopping cart |
unitPrice | Number | Unit price of the product. Pass as a string. |
virtualCategory | String | Category 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
audienceas aJSONObject, not aHashMap. AHashMapvalue is silently dropped by the SDK serializer and the contact will not be mapped.Pass
imageUrlsandproductUrlsas aJSONArrayof 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.JSONObjectBasic example
val data = hashMapOf<String?, Any?>(
"signalType" to "productConfiguration",
"productId" to "SKU-12345",
"productName" to "Wireless Headphones",
"configurationType" to "color"
)
Connect.logSignal(data)Complete example
This example fires a product configuration signal from a product detail bottom sheet when the user selects a colorway. It includes pricing, category, and optional contact mapping.
import org.json.JSONObject
import com.acoustic.connect.android.connectmod.Connect
private fun sendProductConfigurationSignal(configurationType: String) {
// Fields with schema type Number must be passed as strings
val data = hashMapOf<String?, Any?>(
"signalType" to "productConfiguration",
"productId" to product.id,
"productName" to product.name,
"configurationType" to configurationType,
"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 sendProductConfigurationSignal("color") from the colorway chip's checked-change listener, sendProductConfigurationSignal("quantity") from the quantity stepper, and so on.
Troubleshooting
Signal not appearing in Connect?
- Confirm
Connect.enable()is called beforelogSignal. - Check that
logSignalreturnstrue. Afalsereturn indicates the SDK rejected the call. - Verify the
appKeyandpostMessageUrlmatch 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
audienceis aJSONObject, not aHashMap. - Verify attribute key names match exactly how they appear in Connect — including capitalization and spacing.
Too many signals firing?
- For interactions that repeat rapidly (such as quantity steppers), add debouncing logic to avoid sending a signal on every tap.
