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

feat: support item record #38

Merged
merged 5 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,30 @@ ClickstreamAnalytics.recordEvent("testEvent", attributes)
ClickstreamAnalytics.recordEvent("button_click")
```

#### Record event with items

You can add the following code to log an event with an item.

**Note: Only pipelines from version 1.1+ can handle items with custom attribute.**

```swift
import Clickstream

let attributes: ClickstreamAttribute = [
ClickstreamAnalytics.Item.ITEM_ID: "123",
ClickstreamAnalytics.Item.CURRENCY: "USD",
"event_category": "recommended"
]

let item_book: ClickstreamAttribute = [
ClickstreamAnalytics.Item.ITEM_ID: 123,
ClickstreamAnalytics.Item.ITEM_NAME: "Nature",
ClickstreamAnalytics.Item.ITEM_CATEGORY: "book",
ClickstreamAnalytics.Item.PRICE: 99.9
]
ClickstreamAnalytics.recordEvent("view_item", attributes, [item_book])
```

#### Add global attribute

```swift
Expand Down
3 changes: 3 additions & 0 deletions Sources/Clickstream/AWSClickstreamPlugin+ClientBehavior.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ extension AWSClickstreamPlugin {
if let attributes = event.attribute {
clickstreamEvent.addAttribute(attributes)
}
if let items = event.items {
clickstreamEvent.addItems(items)
}

Task {
do {
Expand Down
28 changes: 24 additions & 4 deletions Sources/Clickstream/ClickstreamAnalytics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@ public enum ClickstreamAnalytics {
/// - Parameters:
/// - eventName: the event name
/// - attributes: the event attributes
public static func recordEvent(_ eventName: String, _ attributes: ClickstreamAttribute) {
let event = BaseClickstreamEvent(name: eventName, attribute: attributes)
public static func recordEvent(_ eventName: String,
_ attributes: ClickstreamAttribute,
_ items: [ClickstreamAttribute] = [])
{
let event = BaseClickstreamEvent(name: eventName, attribute: attributes, items: items)
Amplify.Analytics.record(event: event)
}

Expand Down Expand Up @@ -79,11 +82,28 @@ public enum ClickstreamAnalytics {
public static func disable() {
Amplify.Analytics.disable()
}



/// Enable the SDK
/// - Parameter userId: current userId, nil for logout
public static func enable() {
Amplify.Analytics.enable()
}

/// ClickstreamAnalytics item attributes
public enum Item {
static let ITEM_ID = "id"
static let ITEM_NAME = "name"
static let LOCATION_ID = "location_id"
static let ITEM_BRAND = "brand"
static let CURRENCY = "currency"
static let PRICE = "price"
static let QUANTITY = "quantity"
static let CREATIVE_NAME = "creative_name"
static let CREATIVE_SLOT = "creative_slot"
static let ITEM_CATEGORY = "item_category"
static let ITEM_CATEGORY2 = "item_category2"
static let ITEM_CATEGORY3 = "item_category3"
static let ITEM_CATEGORY4 = "item_category4"
static let ITEM_CATEGORY5 = "item_category5"
}
}
9 changes: 8 additions & 1 deletion Sources/Clickstream/ClickstreamAttribute.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
//

import Amplify
import Foundation

/// the attribute for Clickstream which support String, Int, Int64, Double and Bool
public typealias ClickstreamAttribute = AnalyticsProperties

typealias AttributeValue = AnalyticsPropertyValue
/// for support Int64 attribute value
extension Int64: AnalyticsPropertyValue {}
extension Decimal: AnalyticsPropertyValue {}

struct BaseClickstreamEvent: AnalyticsEvent {
var properties: AnalyticsProperties?
Expand All @@ -23,14 +25,19 @@ struct BaseClickstreamEvent: AnalyticsEvent {
/// Properties of the event
var attribute: ClickstreamAttribute?

/// Items of the event
var items: [ClickstreamAttribute]?

/// Initializer
/// - Parameters:
/// - name: The name of the event
/// - attribute: Attribute of the event
init(name: String,
attribute: ClickstreamAttribute? = nil)
attribute: ClickstreamAttribute? = nil,
items: [ClickstreamAttribute]? = nil)
{
self.name = name
self.attribute = attribute
self.items = items
}
}
13 changes: 11 additions & 2 deletions Sources/Clickstream/ClickstreamObjc.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ import Foundation
/// - Parameters:
/// - eventName: the event name
/// - attributes: the event attributes which type is NSDictionary
public static func recordEvent(_ eventName: String, _ attributes: NSDictionary) {
ClickstreamAnalytics.recordEvent(eventName, getAttributes(attributes))
public static func recordEvent(_ eventName: String, _ attributes: NSDictionary, _ items: [NSDictionary] = []) {
ClickstreamAnalytics.recordEvent(eventName, getAttributes(attributes), getItems(items))
}

/// Use this method to send events immediately
Expand Down Expand Up @@ -71,6 +71,15 @@ import Foundation
try ClickstreamAnalytics.getClickstreamConfiguration()
}


private static func getItems(_ items: [NSDictionary]) -> [ClickstreamAttribute] {
var resultItems: [ClickstreamAttribute] = []
for item in items {
resultItems.append(getAttributes(item))
}
return resultItems
}

/// Disable the SDK
public static func disable() {
ClickstreamAnalytics.disable()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ class AnalyticsClient: AnalyticsClientBehaviour {
}

func addGlobalAttribute(_ attribute: AttributeValue, forKey key: String) {
let eventError = Event.checkAttribute(currentNumber: globalAttributes.count, key: key, value: attribute)
let eventError = EventChecker.checkAttribute(
currentNumber: globalAttributes.count,
key: key,
value: attribute)
if eventError.errorCode > 0 {
recordEventError(eventError)
} else {
Expand All @@ -54,7 +57,9 @@ class AnalyticsClient: AnalyticsClientBehaviour {
}

func addUserAttribute(_ attribute: AttributeValue, forKey key: String) {
let eventError = Event.checkUserAttribute(currentNumber: userAttributes.count, key: key, value: attribute)
let eventError = EventChecker.checkUserAttribute(
currentNumber: userAttributes.count,
key: key, value: attribute)
if eventError.errorCode > 0 {
recordEventError(eventError)
} else {
Expand Down Expand Up @@ -115,7 +120,7 @@ class AnalyticsClient: AnalyticsClientBehaviour {
}

func checkEventName(_ eventName: String) -> Bool {
let eventError = Event.checkEventType(eventType: eventName)
let eventError = EventChecker.checkEventType(eventType: eventName)
if eventError.errorCode > 0 {
recordEventError(eventError)
return false
Expand All @@ -139,7 +144,7 @@ class AnalyticsClient: AnalyticsClientBehaviour {
try eventRecorder.save(event)
}

func recordEventError(_ eventError: Event.EventError) {
func recordEventError(_ eventError: EventChecker.EventError) {
Task {
do {
let event = createEvent(withEventType: Event.PresetEvent.CLICKSTREAM_ERROR)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

protocol AnalyticsPropertiesModel {
func addAttribute(_ attribute: AttributeValue, forKey key: String)
func addItem(_ item: ClickstreamAttribute)
}

extension AnalyticsPropertiesModel {
Expand All @@ -15,4 +16,10 @@ extension AnalyticsPropertiesModel {
addAttribute(value, forKey: key)
}
}

func addItems(_ items: [ClickstreamAttribute]) {
for item in items {
addItem(item)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class ClickstreamEvent: AnalyticsPropertiesModel {
let timestamp: Date.Timestamp
let session: Session?
private(set) lazy var attributes: [String: AttributeValue] = [:]
private(set) lazy var items: [ClickstreamAttribute] = []
private(set) lazy var userAttributes: [String: Any] = [:]
let systemInfo: SystemInfo
let netWorkType: String
Expand All @@ -43,7 +44,7 @@ class ClickstreamEvent: AnalyticsPropertiesModel {
}

func addAttribute(_ attribute: AttributeValue, forKey key: String) {
let eventError = Event.checkAttribute(currentNumber: attributes.count, key: key, value: attribute)
let eventError = EventChecker.checkAttribute(currentNumber: attributes.count, key: key, value: attribute)
if eventError.errorCode > 0, key != Event.ReservedAttribute.EXCEPTION_STACK {
attributes[Event.ReservedAttribute.ERROR_CODE] = eventError.errorCode
attributes[Event.ReservedAttribute.ERROR_MESSAGE] = eventError.errorMessage
Expand All @@ -52,6 +53,20 @@ class ClickstreamEvent: AnalyticsPropertiesModel {
}
}

func addItem(_ item: ClickstreamAttribute) {
let checkResult = EventChecker.checkItem(currentNumber: items.count, item: item)
let eventError = checkResult.eventError
let resultItem = checkResult.resultItem
if eventError.errorCode > 0 {
attributes[Event.ReservedAttribute.ERROR_CODE] = eventError.errorCode
attributes[Event.ReservedAttribute.ERROR_MESSAGE] = eventError.errorMessage
} else {
if !resultItem.isEmpty {
items.append(resultItem)
}
}
}

func addGlobalAttribute(_ attribute: AttributeValue, forKey key: String) {
attributes[key] = attribute
}
Expand Down Expand Up @@ -91,19 +106,12 @@ class ClickstreamEvent: AnalyticsPropertiesModel {
event["app_version"] = systemInfo.appVersion
event["app_package_name"] = systemInfo.appPackgeName
event["app_title"] = systemInfo.appTitle
if !items.isEmpty {
event["items"] = items
}
event["user"] = userAttributes
event["attributes"] = getAttributeObject(from: attributes)
return getJsonStringFromObject(jsonObject: event)
}

func getJsonStringFromObject(jsonObject: JsonObject) -> String {
do {
let jsonData = try JSONSerialization.data(withJSONObject: jsonObject, options: [.sortedKeys])
return String(data: jsonData, encoding: .utf8) ?? ""
} catch {
log.error("Error serializing dictionary to JSON: \(error.localizedDescription)")
}
return ""
return event.toJsonString()
}

private func getAttributeObject(from dictionary: AnalyticsProperties) -> JsonObject {
Expand Down
Loading