Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shopper Insights - Added Presentment Details Object and Update Presented Events #1484

Merged
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
905e899
Added presentment details and events
stechiu Dec 12, 2024
e5d5ddd
Addressed PR comments
stechiu Dec 13, 2024
3dbb660
Added doc strings
stechiu Dec 14, 2024
1b9185c
Updated CHANGELOG and unit tests
stechiu Dec 14, 2024
eb83d92
Merge branch 'shopper-insights-rp2-feature' into shopper-insights-rp2…
stechiu Dec 16, 2024
b630541
Addressed PR comments
stechiu Dec 16, 2024
7aebc24
Merge branch 'shopper-insights-rp2-presentment' of https://github.com…
stechiu Dec 16, 2024
31c334a
Addressed PR comments
stechiu Dec 17, 2024
decffcd
Merge branch 'shopper-insights-rp2-feature' into shopper-insights-rp2…
stechiu Dec 17, 2024
ba076e5
Merge branch 'shopper-insights-rp2-presentment' of https://github.com…
stechiu Dec 17, 2024
073cf76
Fixed failing tests
stechiu Dec 17, 2024
b89d854
Removed test from bad merge
stechiu Dec 17, 2024
58895de
Fixed failing unit test
stechiu Dec 17, 2024
4c61f94
Added unit tests
stechiu Dec 17, 2024
590ad21
Added missing unit tests
stechiu Dec 17, 2024
2cc089a
Updated `buttonOrder` and doc strings
stechiu Dec 18, 2024
c1461f6
Removed `experimentType`
stechiu Dec 18, 2024
5ad9668
Updated doc strings
stechiu Dec 19, 2024
57b63f1
Merge branch 'shopper-insights-rp2-presentment' of https://github.com…
stechiu Dec 19, 2024
950b2e0
Fixed failing tests
stechiu Dec 19, 2024
69d5a88
Remove experimentType
warmkesselj Dec 19, 2024
ac4f1ef
Create functions to toggle the paypal or venmo buttons and send prese…
warmkesselj Dec 19, 2024
75674ca
Update docs
warmkesselj Dec 19, 2024
2e6c851
Re add functions that were deleted. Chnage accessor for func used in …
warmkesselj Dec 19, 2024
a9a6f60
Reverse changes to PayPalClient
warmkesselj Dec 19, 2024
3dbdf9a
Remove trailing white space
warmkesselj Dec 19, 2024
0791239
Update Sources/BraintreeShopperInsights/BTPresentmentDetails.swift
jaxdesmarais Dec 20, 2024
c98208d
Merge branch 'shopper-insights-rp2-feature' into shopper-insights-rp2…
warmkesselj Dec 20, 2024
7b5590d
Update
warmkesselj Dec 20, 2024
4095bf5
Update CHANGELOG.md
jaxdesmarais Dec 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions Braintree.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
objects = {

/* Begin PBXBuildFile section */
04AA31182D07974D0043ACAB /* BTButtonType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04AA31172D0797460043ACAB /* BTButtonType.swift */; };
04AA311A2D0797570043ACAB /* BTPresentmentDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04AA31192D0797510043ACAB /* BTPresentmentDetails.swift */; };
04AA311E2D0798FC0043ACAB /* BTPageType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04AA311D2D0798F70043ACAB /* BTPageType.swift */; };
04AA31202D07990E0043ACAB /* BTButtonOrder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04AA311F2D07990A0043ACAB /* BTButtonOrder.swift */; };
04B001102D0CF46E00C0060D /* BTExperimentType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04B0010F2D0CF46900C0060D /* BTExperimentType.swift */; };
0917F6E42A27BDC700ACED2E /* BTVenmoLineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 096C6B2529CCDCEB00912863 /* BTVenmoLineItem.swift */; };
09357DCB2A2FBEC10096D449 /* BTVenmoLineItem_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09357DCA2A2FBEC10096D449 /* BTVenmoLineItem_Tests.swift */; };
1FEB89E614CB6BF0B9858EE4 /* Pods_Tests_IntegrationTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 85BD589D380436A0C9D1DEC1 /* Pods_Tests_IntegrationTests.framework */; };
Expand Down Expand Up @@ -729,6 +734,11 @@
035A59D91EA5DE97002960C8 /* BTLocalPaymentClient_UnitTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BTLocalPaymentClient_UnitTests.swift; sourceTree = "<group>"; };
039A8BD91F9E993500D607E7 /* BTAmericanExpressRewardsBalance_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTAmericanExpressRewardsBalance_Tests.swift; sourceTree = "<group>"; };
03F921C1200EBB200076CD80 /* BTThreeDSecurePostalAddress_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTThreeDSecurePostalAddress_Tests.swift; sourceTree = "<group>"; };
04AA31172D0797460043ACAB /* BTButtonType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTButtonType.swift; sourceTree = "<group>"; };
04AA31192D0797510043ACAB /* BTPresentmentDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTPresentmentDetails.swift; sourceTree = "<group>"; };
04AA311D2D0798F70043ACAB /* BTPageType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTPageType.swift; sourceTree = "<group>"; };
04AA311F2D07990A0043ACAB /* BTButtonOrder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTButtonOrder.swift; sourceTree = "<group>"; };
04B0010F2D0CF46900C0060D /* BTExperimentType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTExperimentType.swift; sourceTree = "<group>"; };
09357DCA2A2FBEC10096D449 /* BTVenmoLineItem_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTVenmoLineItem_Tests.swift; sourceTree = "<group>"; };
096C6B2529CCDCEB00912863 /* BTVenmoLineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTVenmoLineItem.swift; sourceTree = "<group>"; };
162174E1192D9220008DC35D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
Expand Down Expand Up @@ -1494,8 +1504,13 @@
804698292B27C4D70090878E /* BraintreeShopperInsights */ = {
isa = PBXGroup;
children = (
04AA311F2D07990A0043ACAB /* BTButtonOrder.swift */,
stechiu marked this conversation as resolved.
Show resolved Hide resolved
04AA31172D0797460043ACAB /* BTButtonType.swift */,
62EA90482B63071800DD79BC /* BTEligiblePaymentMethods.swift */,
800ED7822B4F5B66007D8A30 /* BTEligiblePaymentsRequest.swift */,
04B0010F2D0CF46900C0060D /* BTExperimentType.swift */,
04AA311D2D0798F70043ACAB /* BTPageType.swift */,
04AA31192D0797510043ACAB /* BTPresentmentDetails.swift */,
8037BFAF2B2CCC130017072C /* BTShopperInsightsAnalytics.swift */,
8064F38E2B1E492F0059C4CB /* BTShopperInsightsClient.swift */,
624B27F62B6AE0C2000AC08A /* BTShopperInsightsError.swift */,
Expand Down Expand Up @@ -3364,11 +3379,16 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
04AA311E2D0798FC0043ACAB /* BTPageType.swift in Sources */,
804698382B27C53B0090878E /* BTShopperInsightsRequest.swift in Sources */,
04B001102D0CF46E00C0060D /* BTExperimentType.swift in Sources */,
04AA31182D07974D0043ACAB /* BTButtonType.swift in Sources */,
624B27F72B6AE0C2000AC08A /* BTShopperInsightsError.swift in Sources */,
804698372B27C5390090878E /* BTShopperInsightsClient.swift in Sources */,
800ED7832B4F5B66007D8A30 /* BTEligiblePaymentsRequest.swift in Sources */,
8037BFB02B2CCC130017072C /* BTShopperInsightsAnalytics.swift in Sources */,
04AA311A2D0797570043ACAB /* BTPresentmentDetails.swift in Sources */,
04AA31202D07990E0043ACAB /* BTButtonOrder.swift in Sources */,
62EA90492B63071800DD79BC /* BTEligiblePaymentMethods.swift in Sources */,
804698392B27C53E0090878E /* BTShopperInsightsResult.swift in Sources */,
);
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
* BraintreeShopperInsights (BETA)
* Add `shopperSessionID` to `BTShopperInsightsClient` initializer
* Add `isPayPalAppInstalled()` and/or `isVenmoAppInstalled()`
* Replace `sendPayPalPresentedEvent()` and `sendPayPalPresentedEvent()` with `sendPresentedEvent(for:presentmentDetails:)`
stechiu marked this conversation as resolved.
Show resolved Hide resolved
* Add values to the following parameters to `presentmentDetails`:
* `experimentType`
* `pageType`
* `buttonOrder`
* Send `url` in `event_params` for App Switch events to PayPal's analytics service (FPTI)
jaxdesmarais marked this conversation as resolved.
Show resolved Hide resolved
* BraintreeVenmo
* Send `url` in `event_params` for App Switch events to PayPal's analytics service (FPTI)
Expand Down
24 changes: 13 additions & 11 deletions Demo/Application/Features/ShopperInsightsViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,16 +104,13 @@ class ShopperInsightsViewController: PaymentButtonBaseViewController {
}

@objc func payPalVaultButtonTapped(_ button: UIButton) {
let sampleExperiment =
"""
[
{ "experimentName" : "payment ready conversion experiment" },
{ "experimentID" : "a1b2c3" },
{ "treatmentName" : "treatment group 1" }
]
"""
let paymentMethods = ["Apple Pay", "Card", "PayPal"]
shopperInsightsClient.sendPayPalPresentedEvent(paymentMethodsDisplayed: paymentMethods, experiment: sampleExperiment)
let presentmentDetails = BTPresentmentDetails(
buttonOrder: .first,
experimentType: .control,
pageType: .about
)

shopperInsightsClient.sendPresentedEvent(for: .payPal, presentmentDetails: presentmentDetails)
progressBlock("Tapped PayPal Vault")
shopperInsightsClient.sendPayPalSelectedEvent()

Expand All @@ -131,7 +128,12 @@ class ShopperInsightsViewController: PaymentButtonBaseViewController {
}

@objc func venmoButtonTapped(_ button: UIButton) {
shopperInsightsClient.sendVenmoPresentedEvent()
let presentmentDetails = BTPresentmentDetails(
buttonOrder: .second,
experimentType: .control,
pageType: .about
)
shopperInsightsClient.sendPresentedEvent(for: .venmo, presentmentDetails: presentmentDetails)
progressBlock("Tapped Venmo")
shopperInsightsClient.sendVenmoSelectedEvent()

Expand Down
16 changes: 16 additions & 0 deletions Sources/BraintreeCore/Analytics/FPTIBatchData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@ struct FPTIBatchData: Codable {
let appSwitchURL: String?
/// UTC millisecond timestamp when a networking task started establishing a TCP connection. See [Apple's docs](https://developer.apple.com/documentation/foundation/urlsessiontasktransactionmetrics#3162615).
/// `nil` if a persistent connection is used.
let buttonOrder: Int?
stechiu marked this conversation as resolved.
Show resolved Hide resolved
let buttonType: String?
let connectionStartTime: Int?
let correlationID: String?
let endpoint: String?
/// UTC millisecond timestamp when a networking task completed.
let endTime: Int?
let errorDescription: String?
let eventName: String
let experimentType: String?
/// True if the `BTConfiguration` was retrieved from local cache after `tokenize()` call.
/// False if the `BTConfiguration` was fetched remotely after `tokenize()` call.
let isConfigFromCache: Bool?
Expand All @@ -48,6 +51,7 @@ struct FPTIBatchData: Codable {
let linkType: String?
/// The experiment details associated with a shopper insights flow
let merchantExperiment: String?
let pageType: String?
/// The list of payment methods displayed, in the same order in which they are rendered on the page, associated with the `BTShopperInsights` flow.
let paymentMethodsDisplayed: String?
/// Used for linking events from the client to server side request
Expand All @@ -65,33 +69,41 @@ struct FPTIBatchData: Codable {

init(
appSwitchURL: URL? = nil,
buttonOrder: Int? = nil,
buttonType: String? = nil,
connectionStartTime: Int? = nil,
correlationID: String? = nil,
endpoint: String? = nil,
endTime: Int? = nil,
errorDescription: String? = nil,
eventName: String,
experimentType: String? = nil,
isConfigFromCache: Bool? = nil,
isVaultRequest: Bool? = nil,
linkType: String? = nil,
merchantExperiment: String? = nil,
pageType: String? = nil,
paymentMethodsDisplayed: String? = nil,
payPalContextID: String? = nil,
requestStartTime: Int? = nil,
shopperSessionID: String? = nil,
startTime: Int? = nil
) {
self.appSwitchURL = appSwitchURL?.absoluteString
self.buttonOrder = buttonOrder
self.buttonType = buttonType
self.connectionStartTime = connectionStartTime
self.correlationID = correlationID
self.endpoint = endpoint
self.endTime = endTime
self.errorDescription = errorDescription
self.eventName = eventName
self.experimentType = experimentType
self.isConfigFromCache = isConfigFromCache
self.isVaultRequest = isVaultRequest
self.linkType = linkType
self.merchantExperiment = merchantExperiment
self.pageType = pageType
self.paymentMethodsDisplayed = paymentMethodsDisplayed
self.payPalContextID = payPalContextID
self.requestStartTime = requestStartTime
Expand All @@ -101,14 +113,18 @@ struct FPTIBatchData: Codable {

enum CodingKeys: String, CodingKey {
case appSwitchURL = "url"
case buttonOrder = "button_order"
stechiu marked this conversation as resolved.
Show resolved Hide resolved
case buttonType = "button_type"
case connectionStartTime = "connect_start_time"
case correlationID = "correlation_id"
case errorDescription = "error_desc"
case eventName = "event_name"
case experimentType = "experiment_type"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just noticed, we don't need this, lets reuse merchantExperiment below

case isConfigFromCache = "config_cached"
case isVaultRequest = "is_vault"
case linkType = "link_type"
case merchantExperiment = "experiment"
case pageType = "page_type"
case paymentMethodsDisplayed = "payment_methods_displayed"
case payPalContextID = "paypal_context_id"
case requestStartTime = "request_start_time"
Expand Down
10 changes: 9 additions & 1 deletion Sources/BraintreeCore/BTAPIClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -303,27 +303,35 @@ import Foundation
@_documentation(visibility: private)
public func sendAnalyticsEvent(
_ eventName: String,
appSwitchURL: URL? = nil,
buttonOrder: Int? = nil,
buttonType: String? = nil,
correlationID: String? = nil,
errorDescription: String? = nil,
experimentType: String? = nil,
merchantExperiment: String? = nil,
isConfigFromCache: Bool? = nil,
isVaultRequest: Bool? = nil,
linkType: LinkType? = nil,
pageType: String? = nil,
paymentMethodsDisplayed: String? = nil,
payPalContextID: String? = nil,
appSwitchURL: URL? = nil,
shopperSessionID: String? = nil
) {
analyticsService.sendAnalyticsEvent(
FPTIBatchData.Event(
appSwitchURL: appSwitchURL,
buttonOrder: buttonOrder,
buttonType: buttonType,
correlationID: correlationID,
errorDescription: errorDescription,
eventName: eventName,
experimentType: experimentType,
isConfigFromCache: isConfigFromCache,
isVaultRequest: isVaultRequest,
linkType: linkType?.rawValue,
merchantExperiment: merchantExperiment,
pageType: pageType,
paymentMethodsDisplayed: paymentMethodsDisplayed,
payPalContextID: payPalContextID,
shopperSessionID: shopperSessionID
Expand Down
33 changes: 33 additions & 0 deletions Sources/BraintreeShopperInsights/BTButtonOrder.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import Foundation

/// The order or ranking in which payment buttons appear.
stechiu marked this conversation as resolved.
Show resolved Hide resolved
/// - Warning: This module is in beta. It's public API may change or be removed in future releases.
public enum BTButtonOrder: Int {
stechiu marked this conversation as resolved.
Show resolved Hide resolved

/// 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets update these docstrings to represent the values accurately

case first

/// 1
case second

/// 2
case third

/// 3
case fourth

/// 4
case fifth

/// 5
case sixth

/// 6
case seventh

/// 7
case eighth

/// 8
case other
}
15 changes: 15 additions & 0 deletions Sources/BraintreeShopperInsights/BTButtonType.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Foundation

/// The button type to be displayed or presented
/// Warning: This module is in beta. It's public API may change or be removed in future releases.
public enum BTButtonType: String {

/// PayPal button
case payPal = "PayPal"

/// Venmo button
case venmo = "Venmo"

/// All button types other than PayPal or Venmo
case other = "Other"
}
21 changes: 21 additions & 0 deletions Sources/BraintreeShopperInsights/BTExperimentType.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import Foundation

/// The experiment type that is sent to analytics to help improve the Shopper Insights feature experience.
/// - Warning: This module is in beta. It's public API may change or be removed in future releases.
public enum BTExperimentType: String {

/// The test experiment
case test

/// The control experiment
case control

public var formattedExperiment: String {
"""
[
{ "exp_name" : "PaymentReady" }
{ "treatment_name" : "\(self.rawValue)" }
]
"""
}
}
45 changes: 45 additions & 0 deletions Sources/BraintreeShopperInsights/BTPageType.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import Foundation

/// The type of page where the event occurred.
/// - Warning: This module is in beta. It's public API may change or be removed in future releases.
public enum BTPageType: String {

/// A home page is the primary landing page that a visitor will view when they navigate to a website.
case homepage = "homepage"

/// An About page is a section on a website that provides information about a company, organization, or individual.
case about = "about"

/// A contact page is a page on a website for visitors to contact the organization or individual providing the website.
case contact = "contact"

/// An intermediary step that users pass through on their way to a product-listing page that doesn't provide a complete
/// list of products but may showcase a few products and provide links to product subcategories.
case productCategory = "product_category"

/// A product detail page (PDP) is a web page that outlines everything customers and buyers need to know about a
/// particular product.
case productDetails = "product_details"

/// The page a user sees after entering a search query.
case search = "search"

/// A cart is a digital shopping cart that allows buyers to inspect and organize items they plan to buy.
case cart = "cart"

/// A checkout page is the page related to payment and shipping/billing details on an eCommerce store.
case checkout = "checkout"

/// An order review page gives the buyer an overview of the goods or services that they have selected and summarizes
/// the order that they are about to place.
case orderReview = "order_review"

/// The order confirmation page summarizes an order after checkout completes.
case orderConfirmation = "order_confirmation"

/// Popup cart displayed after “add to cart” click.
case miniCart = "mini_cart"

/// Any other page available on a merchant’s site.
case other = "other"
}
26 changes: 26 additions & 0 deletions Sources/BraintreeShopperInsights/BTPresentmentDetails.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import Foundation

public class BTPresentmentDetails {

/// The order or ranking in which payment buttons appear.
var buttonOrder: BTButtonOrder

/// The experiment type that is sent to analytics to help improve the Shopper Insights feature experience.
var experimentType: BTExperimentType

/// The type of page where the event occurred.
var pageType: BTPageType
jaxdesmarais marked this conversation as resolved.
Show resolved Hide resolved

/// Detailed information, including button order, experiment type, and page type about the payment button that
/// is sent to analytics to help improve the Shopper Insights feature experience.
/// - Warning: This class is in beta. It's public API may change or be removed in future releases.
stechiu marked this conversation as resolved.
Show resolved Hide resolved
public init(
jaxdesmarais marked this conversation as resolved.
Show resolved Hide resolved
buttonOrder: BTButtonOrder,
experimentType: BTExperimentType,
pageType: BTPageType
) {
self.buttonOrder = buttonOrder
self.experimentType = experimentType
self.pageType = pageType
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import Foundation
enum BTShopperInsightsAnalytics {

// MARK: - Merchant Triggered Events

static let payPalPresented = "shopper-insights:paypal-presented"

static let payPalSelected = "shopper-insights:paypal-selected"
static let venmoPresented = "shopper-insights:venmo-presented"
static let venmoSelected = "shopper-insights:venmo-selected"

static let buttonPresented = "shopper-insights:button-presented"

// MARK: - SDK Triggered Events

Expand Down
Loading