Enable wishlist-item-removed signals in an Android app
The wishlist-item-removed signal fires when a user removes a product from their wishlist or list of saved items. Use this signal to track changes in saved product lists, compare wishlist adds and removes and identify patterns in how contacts manage their saved items.
Availability: Pro, Premium and Ultimate
Languages: Kotlin and Java
Implementation considerations
When to fire the signal
Decide when to send the signal based on your app's behavior:
- On tap - fire as soon as the user taps to remove or un-save the item. Captures intent even if the action fails.
- After confirmation - fire after confirming the item was removed. Ensures accuracy but may miss failed attempts.
For most implementations, firing on tap is recommended.
Multiple removal flows
Users can remove items from a favorites list from different screens in your app:
- Product detail screen - tapping a filled heart button to un-save
- Favorites or saved items screen - a dedicated remove button per item
- Product listing - an un-save icon on a product card
Each screen may have access to different amounts of product data. Make sure all flows are covered and fire one signal per item - including when a user clears all favorites at once.
Contact mapping
Use the audience field to map this 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.
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?>?): 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. If missing, the signal is discarded. |
signalType | String | Signal type. Value: "wishlistItemRemoved". |
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". |
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. |
effect | String | Describes the effect of the signal on engagement. |
externalVariantId | String | Identifier for the specific product variant removed, such as a size or color. |
name | String | A label to differentiate this signal from others (for example, "wishlistItemRemoved from favorites screen"). Max 256 characters. |
price | Number | Price of the product at the time it was removed. Pass as a string (for example, price.toPlainString()). |
productCategory | String | Category or department the product belongs to. |
productName | String | Display name of the product. |
wishlistId | String | Identifier for the specific wishlist the item was removed from, useful if a contact can maintain more than one list. |
Things to know
pricehas schema type Number but must be passed as a string - useprice.toPlainString(). 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.Capture product data before the removal action - after removal the product may no longer be easily accessible.
Optional fields enhance the signal but do not prevent processing if omitted.
Required import
import org.json.JSONObjectBasic example
val data = hashMapOf<String?, Any?>(
"signalType" to "wishlistItemRemoved",
"productId" to "SKU-12345",
"productName" to "Linen Throw",
"price" to "89.99",
"currency" to "USD"
)
Connect.logSignal(data)Complete example
This example fires a wishlist item removed signal when the user taps a filled heart button to un-save the product. The signal fires only when the item is being removed, determined by the return value of the toggle function.
import org.json.JSONObject
import com.acoustic.connect.android.connectmod.Connect
private fun toggleWishlist(product: Product) {
val isNowFaved = FavoritesStore.toggle(product.id)
if (!isNowFaved) {
// Item was just removed from favorites
val data = hashMapOf<String?, Any?>(
"signalType" to "wishlistItemRemoved",
"productId" to product.id,
"productName" to product.name,
"price" to product.price.toPlainString(),
"productCategory" to product.categoryName,
"currency" to "USD",
"category" to "Behavior",
"name" to "wishlistItemRemoved from product detail"
)
// audience must be JSONObject - HashMap values are silently dropped
UserSession.email?.let { email ->
data["audience"] = JSONObject().put("Email Address", email)
}
Connect.logSignal(data)
}
}Troubleshooting
Signal not appearing in Connect?
- Confirm
Connect.enable()is called beforelogSignal. - Capture the return value and check that it is
true:val accepted = Connect.logSignal(data). Afalsereturn indicates the SDK rejected the call - no additional configuration is required to use the return value. - Confirm
productIdis present - it is required and its absence discards the entire signal. - Verify the
appKeyandpostMessageUrlmatch the Connect org you're checking.
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.
Related pages
Updated about 2 hours ago
