Skip to content

Commit

Permalink
Version 2.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
jerielng committed Oct 17, 2023
1 parent 727c0e3 commit 91c7a38
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 3 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
## 2.1.0

#### Added
- Adds the key `subscription_group_state` for setting the subscribed/unsubscribed status when using `braze_subscription_groups` in the Identify call.
- Use this value instead of `subscription_state_id`.
- Adds support for nested custom attributes.
- If the object sent through Segment's `Identify` call has values that are of type `[String: Any?]`, those values will be sent to Braze as a nested custom attribute.
- If the object sent through Segment's `Identify` call contains an array, the values of that array will be converted to strings, and the array will be reported to Braze as an array of strings.

## 2.0.0

#### Added
Expand Down
66 changes: 66 additions & 0 deletions Example/BasicExample/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,72 @@ struct ContentView: View {
traits["phone"] = "1-234-5678"
traits["address"] = ["city": "Paris", "country": "USA"]
traits["foo"] = ["bar": "baz"]
traits["braze_subscription_groups"] = [
[
"subscription_group_id": "1234",
"subscription_group_state": "subscribed"
],
[
"subscription_group_id": "2234",
"subscription_group_state": "unsubscribed"
]
]
traits["any_array"] = [
10,
false,
"string_item"
]
traits["nested_object"] = [
"prop_1": "default",
"prop_2": true,
"prop_3": 1.0,
"nested_array": [
"string",
1.8,
true
],
"string_array": [
"string1",
"string2",
"string3"
],
"double_nested_object": [
"very_nested1": "nest",
"very_nested2": 2.5,
"very_nested_array": [
1,
2,
3
]
]
]
traits["nested_object_array"] = [
[
"array_obj1": true,
"array_obj2": "name"
],
[
"array_obj3": 1.5,
"array_array": [
2.3,
"string",
false,
[
28,
27,
false
],
[
"object1": "name",
"object2": 2.1,
"nested_array": [
25.2,
26.1
]
]
]
]
]
Analytics.main.identify(userId: "X-1234567890", traits: traits)
}
}
Expand Down
65 changes: 63 additions & 2 deletions Sources/SegmentBraze/BrazeDestination.swift
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,8 @@ public class BrazeDestination: DestinationPlugin, VersionedPlugin {
for subscription in subscriptions {
guard
let groupID = subscription[Keys.subscriptionId.rawValue] as? String,
let groupState = subscription[Keys.subscriptionState.rawValue] as? String
let groupState = subscription[Keys.subscriptionGroupState.rawValue] as? String
?? subscription[Keys.subscriptionStateId.rawValue] as? String
else { continue }
switch groupState {
case "subscribed":
Expand Down Expand Up @@ -244,6 +245,13 @@ public class BrazeDestination: DestinationPlugin, VersionedPlugin {
braze.user.setCustomAttribute(key: key, value: value)
case let value as [String]:
braze.user.setCustomAttribute(key: key, array: value)
case let value as [String: Any?]:
braze.user.setCustomAttribute(key: key, dictionary: formatDictionary(value))
case let value as [[String: Any?]]:
let formattedArray = value.map { formatDictionary($0) }
braze.user.setCustomAttribute(key: key, array: formattedArray)
case let value as [Any?]:
braze.user.setCustomAttribute(key: key, array: castToStringArray(value))
default:
braze.user.setCustomAttribute(key: key, value: String(describing: trait.value))
}
Expand Down Expand Up @@ -386,6 +394,58 @@ public class BrazeDestination: DestinationPlugin, VersionedPlugin {
private func log(message: String) {
analytics?.log(message: "[BrazeSegment] \(message)")
}

/// Prepares the object dictionary to be sent upstream to Braze.
private func formatDictionary(_ jsonObject: [String: Any?]) -> [String: Any?] {
jsonObject.mapValues { object in
switch object {
case let stringArray as [String]:
return stringArray
case let jsonArray as [Any?]:
return formatArray(jsonArray)
case let dictionary as [String: Any?]:
return formatDictionary(dictionary)
default:
return object
}
}
}

/// Formats the array to convert any non-string values to strings.
private func formatArray(_ jsonArray: [Any?]) -> [Any] {
jsonArray.compactMap { object in
guard let object else {
self.log(message: "Failed to format JSON array element: \(String(describing: object))")
return nil
}
switch object {
// Short-circuit arrays already containing strings to avoid re-converting them.
case let stringArray as [String]:
return stringArray
case let dictionary as [String: Any?]:
return formatDictionary(dictionary)
case let nestedArray as [Any?]:
return formatArray(nestedArray)
default:
return "\(object)"
}
}
}

/// Fallback to casting the entire array to strings if it doesn't match a Braze-accepted format.
private func castToStringArray(_ jsonArray: [Any?]) -> [String] {
jsonArray.compactMap { object in
guard let object else {
self.log(message: "Failed to stringify JSON array element: \(String(describing: object))")
return nil
}
if let string = object as? String {
return string
} else {
return "\(object)"
}
}
}

// MARK: - Keys

Expand All @@ -396,7 +456,8 @@ public class BrazeDestination: DestinationPlugin, VersionedPlugin {

case subscriptionGroup = "braze_subscription_groups"
case subscriptionId = "subscription_group_id"
case subscriptionState = "subscription_state_id"
case subscriptionStateId = "subscription_state_id"
case subscriptionGroupState = "subscription_group_state"

static let maleTokens: Set<String> = ["m", "male"]
static let femaleTokens: Set<String> = ["f", "female"]
Expand Down
2 changes: 1 addition & 1 deletion Sources/SegmentBraze/Version.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
extension BrazeDestination {
public static let _version = "2.0.0"
public static let _version = "2.1.0"
}

0 comments on commit 91c7a38

Please sign in to comment.