Enable wishlist-item-removed signals in an iOS 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: Swift and Objective-C
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 view controller - 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
Include the audience field to attribute this signal to a contact in Connect. See How behavior signals update Connect data for identifier formats and contact resolution details.
Configuration
Before adding behavior signals, integrate the Connect SDK into your app. A recent beta (debug) version of the SDK is required (2.1.17 or later). See the guide for your development language: Swift or Objective-C.
Method
func logSignal(_ data: [String: Any]?) -> BoolSends the signal to the Acoustic Connect endpoint. Initialize the Connect SDK before calling this method using ConnectSDK.shared.enable(with:).
Pass all fields as a flat [String: Any] dictionary. The SDK handles the signal structure automatically.
- (BOOL)logSignal:(NSDictionary *)values;Sends the signal to the Acoustic Connect endpoint. Initialize the Connect SDK before calling this method using [[ConnectApplicationHelper sharedInstance] enableFramework:withPostMessageUrl:].
Pass all fields as an NSDictionary. The SDK handles the signal structure automatically.
Signal fields
Required
| Field | Type | Description |
|---|---|---|
productId | String | Unique product identifier. If missing, the signal is discarded. |
signalType | String | Signal type. Value: "wishlistItemRemoved". |
Optional
| Field | Type | Description |
|---|---|---|
audience | [String: Any] | Key-value pairs for contact mapping. Keys must match contact attribute names exactly as they appear in Connect, including capitalization and spacing. |
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 from the wishlist |
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
priceaccepts a native Swift numeric type (Double,NSDecimalNumber).Optional fields enhance the signal but do not prevent processing if omitted.
Basic example
import Connect
ConnectCustomEvent.sharedInstance().logSignal([
"signalType": "wishlistItemRemoved",
"productId": "SKU-12345",
"productName": "Linen Throw",
"price": 89.99,
"currency": "USD",
"effect": "negative"
])#import <Connect/Connect.h>
[[ConnectCustomEvent sharedInstance] logSignal:@{
@"signalType": @"wishlistItemRemoved",
@"productId": @"SKU-12345",
@"productName": @"Linen Throw",
@"price": @89.99,
@"currency": @"USD",
@"effect": @"negative"
}];Complete examples
Product detail view controller (heart toggle)
This example fires a wishlist item removed signal from a product detail view controller 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 FavoritesStore.shared.toggle(_:).
import Connect
@objc private func toggleFavorite() {
let isFav = FavoritesStore.shared.toggle(product.id)
favoriteItem.image = UIImage(systemName: isFav ? "heart.fill" : "heart")
favoriteItem.tintColor = isFav ? Theme.accent : Theme.primary
if !isFav {
// Item was just removed from favorites
var signal: [String: Any] = [
"signalType": "wishlistItemRemoved",
"productId": product.id,
"productName": product.name,
"price": product.price.doubleValue,
"productCategory": product.categoryName,
"currency": "USD",
"category": "Behavior",
"effect": "negative",
"name": "wishlistItemRemoved from product detail"
]
if UserSession.shared.isAuthenticated, let email = UserSession.shared.email {
signal["audience"] = ["Email Address": email]
}
let accepted = ConnectCustomEvent.sharedInstance().logSignal(signal)
NSLog("[Connect] wishlistItemRemoved signal accepted: \(accepted)")
}
}#import <Connect/Connect.h>
- (void)toggleFavorite {
BOOL isFav = [FavoritesStore.shared toggle:self.product.id];
self.favoriteItem.image = [UIImage systemImageNamed:isFav ? @"heart.fill" : @"heart"];
self.favoriteItem.tintColor = isFav ? Theme.accent : Theme.primary;
if (!isFav) {
// Item was just removed from favorites
NSMutableDictionary *signal = [@{
@"signalType": @"wishlistItemRemoved",
@"productId": self.product.id,
@"productName": self.product.name,
@"price": @(self.product.price.doubleValue),
@"productCategory": self.product.categoryName,
@"currency": @"USD",
@"category": @"Behavior",
@"effect": @"negative",
@"name": @"wishlistItemRemoved from product detail"
} mutableCopy];
if ([[UserSession shared] isAuthenticated] && [[UserSession shared] email]) {
signal[@"audience"] = @{ @"Email Address": [[UserSession shared] email] };
}
BOOL accepted = [[ConnectCustomEvent sharedInstance] logSignal:signal];
NSLog(@"[Connect] wishlistItemRemoved signal accepted: %@", accepted ? @"true" : @"false");
}
}Favorites screen (remove button)
This example fires a wishlist item removed signal from the favorites screen when the user removes an item from the list. Capture the product data before calling the removal method.
import Connect
private func removeFromFavorites(product: Product) {
// Capture product data before removing
var signal: [String: Any] = [
"signalType": "wishlistItemRemoved",
"productId": product.id,
"productName": product.name,
"price": product.price.doubleValue,
"productCategory": product.categoryName,
"currency": "USD",
"category": "Behavior",
"effect": "negative",
"name": "wishlistItemRemoved from favorites screen"
]
if UserSession.shared.isAuthenticated, let email = UserSession.shared.email {
signal["audience"] = ["Email Address": email]
}
FavoritesStore.shared.toggle(product.id)
let accepted = ConnectCustomEvent.sharedInstance().logSignal(signal)
NSLog("[Connect] wishlistItemRemoved signal accepted: \(accepted)")
}#import <Connect/Connect.h>
- (void)removeFromFavorites:(Product *)product {
// Capture product data before removing
NSMutableDictionary *signal = [@{
@"signalType": @"wishlistItemRemoved",
@"productId": product.id,
@"productName": product.name,
@"price": @(product.price.doubleValue),
@"productCategory": product.categoryName,
@"currency": @"USD",
@"category": @"Behavior",
@"effect": @"negative",
@"name": @"wishlistItemRemoved from favorites screen"
} mutableCopy];
if ([[UserSession shared] isAuthenticated] && [[UserSession shared] email]) {
signal[@"audience"] = @{ @"Email Address": [[UserSession shared] email] };
}
[FavoritesStore.shared toggle:product.id];
BOOL accepted = [[ConnectCustomEvent sharedInstance] logSignal:signal];
NSLog(@"[Connect] wishlistItemRemoved signal accepted: %@", accepted ? @"true" : @"false");
}Best practices
- Capture product data before the removal action - after removal the product may no longer be easily accessible.
- Fire one signal per item removed, even when a user clears the entire favorites list at once.
- Always include an
audienceidentifier - pairing removals with additions is what makes win-back analysis work. - Omit
priceandcurrencyrather than sending placeholder values.
Verification
After tapping the heart icon again to remove a saved product or swiping to remove an item from the Favorites screen, check the Xcode console for:
[Connect] wishlistItemRemoved signal accepted: true
The false value means the SDK rejected the call - see Troubleshooting below. Once the console confirms acceptance, verify the signal is available in Connect.
Troubleshooting
Signal not appearing in Connect?
- Confirm the Connect SDK is initialized before any signal calls. See Method.
- Capture the return value:
let accepted = ConnectCustomEvent.sharedInstance().logSignal(signal). Afalsereturn indicates the SDK rejected the call. - Confirm
productIdis present - it is required and its absence discards the entire signal. - Verify the
appKeyandpostURLmatch the Connect org you're checking.
Contact not created or updated?
- Verify attribute key names in
audiencematch exactly how they appear in Connect - including capitalization and spacing.
Related pages
Updated about 2 hours ago
