braze-inc / braze-flutter-sdk

Public repo for the Braze Flutter SDK
Other
15 stars 29 forks source link

logContentCardClicked implements different behaviour when url is set #45

Closed RutgerVleuten closed 1 year ago

RutgerVleuten commented 1 year ago

Calling logContentCardClicked with the below content, the 3.1.0 SDK launches the phones browser which is different from the 2.5.0 SDK where no browser is opened.

This change in behaviour effects the custom UI flow that we have implemented.

contentCardJsonString = "{}" clicked = true created = 1677231900 description = "Description" dismissable = true expiresAt = 1679651100 extras = {_Map} size = 4 id = "some id" image = "Image url" imageAspectRatio = 2.0 linkText = "Link text" pinned = false removed = false title = "Title" type = "captioned_image" url = "https://google.com" useWebView = false viewed = true isControl = false

note: this seems to happen on iOS only, wil post a reference to this ticket.

https://github.com/braze-inc/braze-swift-sdk/issues/49

hokstuff commented 1 year ago

Hi @RutgerVleuten,

To clarify, in 2.5.0 was the link opening inside a webview in the app while in 3.1.0, it is opening an external browser? In other words, does that mean the useWebView field is not being respected in 3.1.0?

Are you doing any native customization, such as using BrazeDelegate methods?

RutgerVleuten commented 1 year ago

Hey Hey, thanks for your reply.

In 2.5.0 no browser is opened, this is still the case on Android for 3.1.0 but on iOS an external browser is opened.

In the native side we only init braze and subscribe to content card updates and messages in the following way:

let braze = BrazePlugin.initBraze(config)

contentCardsSubscription = braze.contentCards.subscribeToUpdates { contentCards in BrazePlugin.processContentCards(contentCards) }

messagePresenter.delegate = self braze.inAppMessagePresenter = messagePresenter

func inAppMessage( _ ui: BrazeInAppMessageUI, displayChoiceForMessage message: Braze.InAppMessage ) -> BrazeInAppMessageUI.DisplayChoice { BrazePlugin.processInAppMessage(message) return .discard }

hokstuff commented 1 year ago

Hi @RutgerVleuten,

We are unable to reproduce this behavior in our sample app. When testing, this is the logging that prints when a Content card is clicked that opens the URL inside a webview in the app:

2023-02-27 11:43:58.398135-0500 Runner[4830:4029681] [braze] Opening 'https://example.com':
- channel: contentCard
- useWebView: true
- extras: {}

and this is the logging when it opens the URL in an external browser:

2023-02-27 11:44:21.482030-0500 Runner[4830:4030479] [braze] Opening 'https://example.com':
- channel: contentCard
- useWebView: false
- extras: {}
=> [Content Card Subscription] Received cards:
/* Other logging*/

The sample app doesn't do customization in the native layer outside of anything found here.


The field that determines whether or not to display a ClickAction inside the app vs in an external browser is useWebView.

  1. Can you double check that the campaigns you are triggering have the expected fields checked to ensure it is opened inside a browser? Also, can you attach any relevant campaigns to this ticket or send it to Support so we can check as well?
  2. Do you use the default Content Card UI, and do you have any custom logic around the click actions? Can you also attach relevant logging when clicking the Content Card to check if the Content Card JSON is being parsed as expected (feel free to use this API)?
  3. Do you perform any customization in the Dart layer for Content Cards?
RutgerVleuten commented 1 year ago

Hi @hokstuff,

Thank you for clarifying the useWebview field, my understanding was that when this field is false no browser is shown.

What I find is that the the Android SDK on 3.1.0 does not show a browser nor an in-app web view regardless of what the value is for useWebview (see logging below).

V/Braze v24.2.0 .p( 7188): Attempting to log event: { V/Braze v24.2.0 .p( 7188): "name": "ccc", V/Braze v24.2.0 .p( 7188): "data": { V/Braze v24.2.0 .p( 7188): "ids": [ V/Braze v24.2.0 .p( 7188): "NjFhMGY0Zjg3MzEzNjA3YzA4YzIyY2M5XyRfY2M9MzJmZjNmNGYtYTVmNi1lMGQ0LTRlOWItMzM1NTI3MDdkMDE1Jm12PTYxYTBmNGY4NzMxMzYwN2MwOGMyMmNiOSZwaT1jbXA=" V/Braze v24.2.0 .p( 7188): ] V/Braze v24.2.0 .p( 7188): }, V/Braze v24.2.0 .p( 7188): "time": 1.677521617609E9, V/Braze v24.2.0 .p( 7188): "user_id": "user0", V/Braze v24.2.0 .p( 7188): "session_id": "98613c68-8d20-404f-8dea-a92e7b8bf197" V/Braze v24.2.0 .p( 7188): } D/Braze v24.2.0 .j5( 7188): Adding event to storage with uid b18ac338-2d5e-4826-96e7-4de8adfe1894 D/Braze v24.2.0 .a1( 7188): bo.app.p0 fired: commandType = ADD_BRAZE_EVENT D/Braze v24.2.0 .a1( 7188): brazeEvent = {"name":"ccc","data":{"ids":["NjFhMGY0Zjg3MzEzNjA3YzA4YzIyY2M5XyRfY2M9MzJmZjNmNGYtYTVmNi1lMGQ0LTRlOWItMzM1NTI3MDdkMDE1Jm12PTYxYTBmNGY4NzMxMzYwN2MwOGMyMmNiOSZwaT1jbXA="]},"time":1.677521617609E9,"user_id":"user0","session_id":"98613c68-8d20-404f-8dea-a92e7b8bf197"} D/Braze v24.2.0 .a1( 7188): sessionId = null D/Braze v24.2.0 .a1( 7188): brazeRequest = null D/Braze v24.2.0 .a1( 7188): Triggering bo.app.p0 on 1 subscribers. D/Braze v24.2.0 .CaptionedImageCard( 7188): Logged click for card with id: NjFhMGY0Zjg3MzEzNjA3YzA4YzIyY2M5XyRfY2M9MzJmZjNmNGYtYTVmNi1lMGQ0LTRlOWItMzM1NTI3MDdkMDE1Jm12PTYxYTBmNGY4NzMxMzYwN2MwOGMyMmNiOSZwaT1jbXA= D/EGL_emulation( 7188): app_time_stats: avg=80.58ms min=1.73ms max=880.02ms count=12 I/Braze v24.2.0 .Braze( 7188): Requesting immediate data flush to Braze.

radixdev commented 1 year ago

Hi @RutgerVleuten ,

RutgerVleuten commented 1 year ago
radixdev commented 1 year ago

Hi @RutgerVleuten ,

I see the original URL 👍🏽 from the dashboard link. Can you provide android verbose logs of you clicking that content card, starting from a fresh start of the app to a few seconds after the click (the file should be large and that is desired). Only with those full unabbreviated logs we can see why does not show a browser nor an in-app web view regardless of what the value is for useWebview.

hokstuff commented 1 year ago

Thank you for clarifying the useWebview field, my understanding was that when this field is false no browser is shown.

The actual expected behavior across both platforms is:

RutgerVleuten commented 1 year ago

The actual expected behavior across both platforms is:

  • useWebview is false: The URL is opened in an external browser (Chrome, Safari, etc)
  • useWebview is true: The URL is opened in a webview inside the app

The actual behaviour of calling logContentCardClicked with a content card from a campaign that has an URL setup for both iOS and Android is as follows:

Version 2.5.0

Android:

iOS:

Version 3.1.0

Android:

iOS:

note: to verify I used the code from Braze sample application with no native customisations.

This is the campaign link: https://dashboard-03.braze.com/engagement/campaigns/61a0f4f87313607c08c22cc9/5b640dc77dea0d1ec60ce16f

Maybe useful, the JSON string: {\"ar\":1.7789473684210526,\"ca\":1677583114,\"cl\":true,\"db\":true,\"dm\":\"Check\",\"ds\":\"Use Halloween pathway lights\\nOnly the bravest trick-or-treaters will dare to approach your door when you use smart light to illuminate the path. Outdoor lightstrips are a favorite for Halloween, as you can snake them along winding paths and set them to any color \u2014 try orange, purple, or green \u2014 to creep out your Halloween visitors.\\n\\nHighlight your spookiest decor\\nCreate a cemetery in your front yard with DIY gravestones, and then place Lily spotlights in between them. With their powerful beams of light, Lily spotlights can create interesting shadows \u2014 making your outdoor Halloween decorations that much more dynamic.\",\"e\":{\"contentCardType\":\"whatsnew\",\"launchDate\":\"2022-03-28\",\"overline\":\"Feature\"},\"ea\":1677583414,\"i\":\"https:\/\/braze-images.com\/appboy\/communication\/marketing\/content_cards_message_variations\/images\/61a0f4f87313607c08c22cb9\/1eebefe4d98810de74837cff0ff0accec778e002\/original.jpeg?1637938572\",\"id\":\"NjFhMGY0Zjg3MzEzNjA3YzA4YzIyY2M5XyRfY2M9OTI0ZmE4ZWUtZTM5MC1hNTMyLWI1ZTctNWMxYTBiNmUzM2U1Jm12PTYxYTBmNGY4NzMxMzYwN2MwOGMyMmNiOSZwaT1jbXA=\",\"p\":false,\"r\":false,\"t\":false,\"tp\":\"captioned_image\",\"tt\":\"Outdoor Halloween lighting ideas\",\"u\":\"https:\/\/www.philips-hue.com\/en-us\/explore-hue\/blog\/halloween-lighting-ideas\",\"uw\":false,\"v\":false}

@hokstuff could you please verify this on your side?

JordyLangen commented 1 year ago

Aside from this regression, it's also just weird.

The documentation for logContentCardClicked is:

/// Logs a click for the provided Content Card data.

It does not mention that it will also open the url (apparently)

RutgerVleuten commented 1 year ago

Indeed @JordyLangen it does not make any sense that useWebview is considered in case of logging a click. It should only apply when braze is showing a UI like in case of launchContentCards(), there we have a "read more" button.

Digging a bit deeper in code from line 79 of the BrazePlugin:

    if let contentCard = BrazePlugin.contentCard(from: contentCardJSONString, braze: braze) {
        contentCard.logClick(using: braze)
     }

I see that thecontentCard.clickAction is <invalid> (0x0)

When changing it to:

      if var contentCard = BrazePlugin.contentCard(from: contentCardJSONString, braze: braze) {
        contentCard.clickAction = .none
        contentCard.logClick(using: braze)
      }

All works fine, so probably something goes wrong when creating the contentCard from the jsonString.

@hokstuff, could you please check this?

hokstuff commented 1 year ago

Hi @RutgerVleuten and @JordyLangen,

Thanks for the deep investigation into this issue! We have found the root cause of the issue, and it applies to both content cards and in-app messages, specifically when using custom UIs.

The underlying behavior of the Braze Swift SDK's API being called here and here currently logs a clicked event for metrics AND processes the click action (e.g. redirect to URL), when it should only do the former. It is up to the host app to use the url field to process the click action, such as redirect, so that Swift SDK API will be updated. This change will then be consistent with the Android behavior and the Flutter SDK's iOS behavior on 2.x.x.

In the meantime, the proposal noted here might be a temporary workaround if you are using a fully custom UI. It will cause no clickAction that gets executed on iOS to be a no-op, meaning no browser / webview will be launched.

hokstuff commented 1 year ago

Hi @RutgerVleuten and @JordyLangen,

We have released Flutter SDK version 4.0.0 which fixes the behavior described above by reverting the functionality of iOS to match that of Android when logging clicks when using a custom UI.

For example, when calling logContentCardClick, the API now only sends a click event to the backend, and it doesn't process any url associated with that content card. Processing the url field is up to the host app, which is the behavior on iOS in version 2.x, and the Android behavior in all versions. Also note any possible integration changes which are called out in the Changelog.

Let us know if you have further questions - thanks!

jocelynzz commented 1 year ago

Hey @RutgerVleuten and @JordyLangen, I am following up on @hokstuff 's last message last week. Did you get a chance to try the latest version of the Flutter SDK? Would appreciate it if you could confirm the issue is resolved on your end. :)

JordyLangen commented 1 year ago

@hokstuff @jocelynzz we had some issues updating, we think because the version number here: https://github.com/braze-inc/braze-flutter-sdk/blob/master/ios/braze_plugin.podspec is still 3.1.0. We had to delete the Podfile.lock as we where not able to pod install:

[!] CocoaPods could not find compatible versions for pod "BrazeLocation":
  In snapshot (Podfile.lock):
    BrazeLocation (= 5.9.1, ~> 5.9.0)

  In Podfile:
    braze_plugin (from `.symlinks/plugins/braze_plugin/ios`) was resolved to 3.1.0, which depends on
      BrazeLocation (~> 5.11.2)

You have either:
 * out-of-date source repos which you can update with `pod repo update` or with `pod install --repo-update`.
 * changed the constraints of dependency `BrazeLocation` inside your development pod `braze_plugin`.
   You should run `pod update BrazeLocation` to apply changes you've made.
hokstuff commented 1 year ago

@JordyLangen Thanks for pointing out that issue and your workaround! We are currently preparing a new release which will fix this versioning issue.

Additionally, we've slotted in future work to further automate our release process with the intention to avoid manual errors such as this in the future.

hokstuff commented 1 year ago

Hi @JordyLangen,

We have just released Flutter SDK version 4.1.0 which fixes the podspec version number issue - thanks for your patience!