braze-inc / braze-swift-sdk

https://www.braze.com
Other
48 stars 19 forks source link

[Bug]: BrazeInAppMessageUIDelegate, discarding a Test Send in-app message isn’t discarding it #88

Closed remziyildirim closed 5 months ago

remziyildirim commented 8 months ago

Platform

iOS

Platform Version

iOS 15.0

Braze SDK Version

7.0.0

Xcode Version

Xcode 15.0

Computer Processor

Apple (M1)

Repro Rate

100%

Steps To Reproduce

We use key-value pairs in some in-app messages to navigate the user to customised screen. When returning BrazeInAppMessageUI.DisplayChoice.discard display choice in the braze in-app message, it isn't discarding the message. Every time moving the app foreground -> background -> foreground or kill it and run it again, the Braze SDK calls func inAppMessage(_ ui: BrazeInAppMessageUI, displayChoiceForMessage message: Braze.InAppMessage) -> BrazeInAppMessageUI.DisplayChoice function again and again for the same in-app message.

   func inAppMessage(
        _ ui: BrazeInAppMessageUI,
        displayChoiceForMessage message: Braze.InAppMessage
    ) -> BrazeInAppMessageUI.DisplayChoice {

        if let campaignId = message.extras["CampaignId"] as? String {
            // Open related campaign screen via deeplinking.
            // Deeplinking.open(.campaing(id: campaignId))

            return .discard
        }
        return .now
    }

Expected Behavior

It should work without message.context?.logImpression().

   func inAppMessage(
        _ ui: BrazeInAppMessageUI,
        displayChoiceForMessage message: Braze.InAppMessage
    ) -> BrazeInAppMessageUI.DisplayChoice {

        if let campaignId = message.extras["CampaignId"] as? String {
            // Open related campaign screen via deeplinking.
            // Deeplinking.open(.campaing(id: campaignId))

            return .discard
        }
        return .now
    }

Actual Incorrect Behavior

We're currently using message.context?.logImpression()to avoid the repeated triggering of this Braze delegate function by BrazeSDK.

   func inAppMessage(
        _ ui: BrazeInAppMessageUI,
        displayChoiceForMessage message: Braze.InAppMessage
    ) -> BrazeInAppMessageUI.DisplayChoice {

        if let campaignId = message.extras["CampaignId"] as? String {
            // Open related campaign screen via deeplinking.
            // Deeplinking.open(.campaing(id: campaignId))

            // Added to prevent in-app-message loop. Returning `discard` is not enough to dismiss the in-app-message.
            message.context?.logImpression()
            return .discard
        }
        return .now
    }

Verbose Logs

No response

Additional Information

No response

jacksonemiller commented 8 months ago

Hi @remziyildirim, as long as a user continues to be re-eligible for an in-app message, they will keep receiving it every time you hit the trigger condition. Returning .discard removes the IAM currently on the stack of IAMs ready to be displayed, but the IAM can be re-added to the stack in the future if the trigger condition is met again.

Could I ask what display behavior you were observing without your fix? Specifically, when you mentioned the delegate method was getting called again and again, did you mean in some sort of a loop, or just once every time you backgrounded and then foregrounded the app? Additionally, could I ask what sort of a trigger condition is involved here?

Thank you!

remziyildirim commented 8 months ago

Hey @jacksonemiller,

You're right, we have no doubt about being called when the condition is met again.

Actually, we were testing it via Preview Test of IAM in Braze dashboard. After we have sent it only once, a loop stars on the application side. By loop I mean, after every time we have backgrounded and then foregrounded the app, the delegate function (asking display choice for IAM) is called again for the same IAM by Braze SDK. The situation continues even when we kill the application and run it again. If you want I can prepare I demo video as well.

Additionally, the behaviour we expect is that the IAM message, which we send only once via the Preview Test, is not shown again once it has been discarded. Because we're trying to discard the message with the .discard option. If we had used the .later option, we would have no objection to the message being shown again when the conditions are met.

jacksonemiller commented 8 months ago

Ah okay, I didn't initially realize this was for a test send. Thank you for the additional information. I was able to reproduce the issue you described and this is indeed not our intended behavior with test sends, so I've filed a change internally to address the issue. We will keep you updated with any developments.

Thank you!

jonathanarydm commented 7 months ago

Hello! Any update on this issue? I can reproduce the same behavior. Thanks!

jacksonemiller commented 7 months ago

Hi again,

We are continuing to work on a solution for this and will definitely let you know when we release a fix. Thank you again for bringing this issue to our attention.

Thanks.

drezzzik commented 7 months ago

I faced the same issue with the latest SDK version (7.4.0). It is present at least from 5.13. I initiated a campaign with enabled flag "Allow users to become re-eligible to receive campaign", and after some time disabled this flag. But the in-app messages are still coming to iOS device, with the initially defined interval.

jacksonemiller commented 6 months ago

HI @drezzzik.

Just to confirm, are you also only observing this with test sends, or have you experienced it happening on a broader level? If you've been observing an issue beyond test sends initiated from the IAM editor in the dashboard, we definitely would like to hear more about it, and I would ask if you could please create a separate bug report on this repository.

Thank you!

jacksonemiller commented 5 months ago

Hi @remziyildirim. We just released a fix for this in version 7.6.0 of the Braze Swift SDK. I'm going to go ahead and close this thread for now, but feel free to re-open it or contact us if you have any other issues. Thanks again for the bug report.