Skip to content

Commit

Permalink
[NT-645] Clean discovery properties & events [Part 1] (#984)
Browse files Browse the repository at this point in the history
* WIP cleaning up discovery properties

* Cleaning up events

* Updating tests

* Formatting

* Reverting scheme change

* Line length

* Remove category_projects_count prop

* Updates

* Formatting

* Cleanup

* Formatting

* RefTag fromParams tests and snake-casing search term
  • Loading branch information
Isabel Barrera committed Dec 10, 2019
1 parent 6dfa3c6 commit e3748d2
Show file tree
Hide file tree
Showing 22 changed files with 310 additions and 517 deletions.
22 changes: 22 additions & 0 deletions Library/RefTag.swift
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,25 @@ extension RefTag: Argo.Decodable {
}
}
}

extension RefTag {
public static func fromParams(_ params: DiscoveryParams) -> RefTag {
if let tagId = params.tagId {
return .projectCollection(tagId)
}

if params.category != nil {
return .categoryWithSort(params.sort ?? .magic)
} else if params.recommended == .some(true) {
return .recsWithSort(params.sort ?? .magic)
} else if params.staffPicks == .some(true) {
return .recommendedWithSort(params.sort ?? .magic)
} else if params.social == .some(true) {
return .socialWithSort(params.sort ?? .magic)
} else if params.starred == .some(true) {
return .starredWithSort(params.sort ?? .magic)
}

return RefTag.discoveryWithSort(params.sort ?? .magic)
}
}
28 changes: 28 additions & 0 deletions Library/RefTagTests.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
@testable import KsApi
@testable import Library
import Prelude
import XCTest

public final class RefTagTests: XCTestCase {
Expand Down Expand Up @@ -173,4 +175,30 @@ public final class RefTagTests: XCTestCase {
XCTAssertEqual(RefTag.update, RefTag(code: RefTag.update.stringTag))
XCTAssertEqual(RefTag.unrecognized("custom"), RefTag(code: RefTag.unrecognized("custom").stringTag))
}

func testRefTagFromDiscoveryParams() {
let discoSort = DiscoveryParams.defaults
|> DiscoveryParams.lens.sort .~ .endingSoon
let discoCategory = DiscoveryParams.defaults
|> DiscoveryParams.lens.sort .~ .endingSoon
|> DiscoveryParams.lens.category .~ Category.documentary
let discoRecommended = DiscoveryParams.defaults
|> DiscoveryParams.lens.recommended .~ true
let discoPWL = DiscoveryParams.defaults
|> DiscoveryParams.lens.staffPicks .~ true
let discoSocial = DiscoveryParams.defaults
|> DiscoveryParams.lens.social .~ true
let discoStarred = DiscoveryParams.defaults
|> DiscoveryParams.lens.starred .~ true
let discoCollection = DiscoveryParams.defaults
|> DiscoveryParams.lens.tagId .~ .goRewardless

XCTAssertEqual("discovery_ending_soon", RefTag.fromParams(discoSort).stringTag)
XCTAssertEqual("category_ending_soon", RefTag.fromParams(discoCategory).stringTag)
XCTAssertEqual("recs_home", RefTag.fromParams(discoRecommended).stringTag)
XCTAssertEqual("recommended_home", RefTag.fromParams(discoPWL).stringTag)
XCTAssertEqual("social_home", RefTag.fromParams(discoSocial).stringTag)
XCTAssertEqual("starred_home", RefTag.fromParams(discoStarred).stringTag)
XCTAssertEqual("ios_project_collection_tag_518", RefTag.fromParams(discoCollection).stringTag)
}
}
195 changes: 56 additions & 139 deletions Library/Tracking/Koala.swift
Original file line number Diff line number Diff line change
Expand Up @@ -400,23 +400,15 @@ public final class Koala {
self.preferredContentSizeCategoryObserver.doIfSome(NotificationCenter.default.removeObserver)
}

// MARK: - Activity

/// Call when the activities screen is shown.
public func trackActivities() {
self.track(event: "Activities", properties: deprecatedProps)
self.track(event: "Viewed Activity")
public func trackActivities(count: Int) {
// TODO: add user properties and session props
self.track(event: "Activity Feed Viewed", properties: ["activities_count": count])
}

/// Call when the activities are refreshed.
public func trackLoadedNewerActivity() {
self.track(event: "Loaded Newer Activity")
}

/// Call when the activities are paginated.
///
/// - parameter page: The number of pages that have been loaded.
public func trackLoadedOlderActivity(page: Int) {
self.track(event: "Loaded Older Activity", properties: ["page": page])
}
// MARK: - Application Lifecycle

/// Call when the app launches or enters foreground.
public func trackAppOpen() {
Expand Down Expand Up @@ -480,122 +472,57 @@ public final class Koala {
// MARK: - Discovery Events

/**
Call when a discovery search is made, including pagination.
Call when a discovery page is viewed and the first page is loaded.
- parameter params: The params used for the discovery search.
- parameter page: The number of pages that have been loaded.
*/
public func trackDiscovery(params: DiscoveryParams, page: Int) {
var props = properties(params: params).withAllValuesFrom(["page": page])

self.track(event: "Loaded Discovery Results", properties: props)

// Deprecated event
self.track(
event: "Discover List View",
properties: props.withAllValuesFrom(deprecatedProps)
)
}

public func trackDiscoveryViewed(params: DiscoveryParams) {
self.track(event: "Viewed Discovery", properties: properties(params: params))
}

public func trackDiscoveryFavoritedCategory(params: DiscoveryParams, isFavorited: Bool) {
let props = params.category.map(properties) ?? [:]
let deprecatedProps = props.withAllValuesFrom(
["toggle_to": isFavorited, Koala.DeprecatedKey: true]
)

self.track(
event: isFavorited ? "Added Favorite Category" : "Removed Favorite Category",
properties: props
)

// Deprecated event
self.track(
event: "Discover Category Favorite",
properties: deprecatedProps
)
}
public func trackDiscovery(params: DiscoveryParams) {
let props = discoveryProperties(from: params)

/// Call when the discovery filters appear
public func trackDiscoveryModal() {
let props: [String: Any] = ["modal_type": "filters"]

self.track(event: "Viewed Discovery Filters", properties: props)

// Deprecated event
self.track(
event: "Discover Switch Modal",
properties: props.withAllValuesFrom(deprecatedProps)
)
self.track(event: "Explore Page Viewed", properties: props)
}

/**
Call when a filter is selected from the discovery modal.
Call when a filter is selected from the Explore modal.
- parameter params: The params selected from the modal.
- parameter isFavorite: Whether the filter is a favorite category or not.
*/
public func trackDiscoveryModalSelectedFilter(params: DiscoveryParams, isFavorite: Bool = false) {
public func trackDiscoveryModalSelectedFilter(params: DiscoveryParams) {
self.track(
event: "Selected Discovery Filter",
properties: properties(params: params).withAllValuesFrom([
"is_favorite": isFavorite ? "1" : "0"
])
event: "Filter Clicked",
properties: discoveryProperties(from: params)
)

// Deprecated event
self.track(
event: "Discover Modal Selected Filter",
properties: properties(params: params).withAllValuesFrom(deprecatedProps)
)
}

/**
Call when closing filter modal without selecting a new filter.
- parameter params: The params selected from the modal.
**/
public func trackDiscoveryModalClosedFilter(params: DiscoveryParams) {
self.track(event: "Closed Discovery Filter", properties: properties(params: params))
}

/**
Call when expanding filter on a parent category tap.
- parameter params: The params selected from the modal.
**/
public func trackDiscoveryModalExpandedFilter(params: DiscoveryParams) {
self.track(event: "Expanded Discovery Filter", properties: properties(params: params))
}

/**
Call when the user swipes between sorts or selects a sort.
- parameter sort: The new sort that was selected.
- parameter gesture: The gesture that was used.
*/
public func trackDiscoverySelectedSort(nextSort sort: DiscoveryParams.Sort, gesture: GestureType) {
self.track(event: "Selected Discovery Sort", properties: [
"discover_sort": sort.rawValue,
"gesture_type": gesture.trackingString
])
public func trackDiscoverySelectedSort(nextSort sort: DiscoveryParams.Sort, params: DiscoveryParams) {
let props = discoveryProperties(from: params)
.withAllValuesFrom([
"discover_sort": sort.rawValue
])

self.track(event: "Explore Sort Clicked", properties: props)
}

/**
Call when the user drags the top of the project list downward to refresh projects.
Call when the user taps the editorial header at the top of Discovery
*/
public func trackDiscoveryPullToRefresh() {
self.track(event: "Triggered Refresh")
public func trackEditorialHeaderTapped(refTag: RefTag) {
self.track(event: "Editorial Card Clicked", properties: ["ref_tag": refTag.stringTag])
}

/**
Call when the user taps the editorial header at the top of Discovery
Call when a collection is viewed
- parameter params: The DiscoveryParams associated with the collection
*/
public func trackEditorialHeaderTapped(refTag: RefTag) {
self.track(event: "Editorial Card Clicked", properties: ["refTag": refTag.stringTag])
public func trackCollectionViewed(params: DiscoveryParams) {
self.track(event: "Collection Viewed", properties: discoveryProperties(from: params))
}

// MARK: - Checkout Events
Expand Down Expand Up @@ -1320,31 +1247,25 @@ public final class Koala {

/// Call once when the search view is initially shown.
public func trackProjectSearchView() {
self.track(event: "Discover Search", properties: deprecatedProps)

self.track(event: "Viewed Search")
// TODO: pass user properties, session properties
self.track(event: "Search Page Viewed")
}

// Call when projects have been obtained from a search.
public func trackSearchResults(query: String, page: Int, hasResults: Bool) {
let sharedProps: [String: Any] = ["search_term": query]

let deprecatedProps = sharedProps.withAllValuesFrom(["page_count": page, Koala.DeprecatedKey: true])
let props = sharedProps.withAllValuesFrom(["page": page, "has_results": hasResults])

if page == 1 {
self.track(event: "Discover Search Results", properties: deprecatedProps)

self.track(event: "Loaded Search Results", properties: props)
} else {
self.track(event: "Discover Search Results Load More", properties: deprecatedProps)

self.track(event: "Loaded More Search Results", properties: props)
}
}
public func trackSearchResults(
query: String,
params: DiscoveryParams,
refTag: RefTag,
hasResults: Bool
) {
let props = discoveryProperties(from: params)
.withAllValuesFrom([
"discover_ref_tag": refTag.stringTag,
"search_term": query,
"has_results": hasResults
])

public func trackClearedSearchTerm() {
self.track(event: "Cleared Search Term")
self.track(event: "Search Results Loaded", properties: props)
}

// MARK: - Project Events
Expand Down Expand Up @@ -1950,13 +1871,6 @@ public final class Koala {

// MARK: - Empty State Events

public func trackEmptyStateViewed(type: EmptyState) {
self.track(
event: "Viewed Empty State",
properties: ["type": type.rawValue]
)
}

public func trackEmptyStateButtonTapped(type: EmptyState) {
self.track(
event: "Tapped Empty State Button",
Expand Down Expand Up @@ -2254,34 +2168,37 @@ private func properties(userActivity: NSUserActivity) -> [String: Any] {
return props
}

private func properties(params: DiscoveryParams, prefix _: String = "discover_") -> [String: Any] {
// MARK: - Discovery Properties

private func discoveryProperties(
from params: DiscoveryParams,
prefix: String = "discover_"
) -> [String: Any] {
var result: [String: Any] = [:]
var unprefixedResult: [String: Any] = [:]

// NB: All filters should be added here since `result["everything"]` is derived from this.
result["recommended"] = params.recommended
result["social"] = params.social
result["staff_picks"] = params.staffPicks
result["starred"] = params.starred
result["term"] = params.query
result["tag"] = params.tagId?.rawValue
result = result.withAllValuesFrom(params.category.map(properties(category:)) ?? [:])

result["everything"] = result.isEmpty
result["page"] = params.page
result["sort"] = params.sort?.rawValue
result["ref_tag"] = RefTag.fromParams(params).stringTag

return result.prefixedKeys("discover_")
unprefixedResult["search_term"] = params.query

return result.prefixedKeys(prefix).withAllValuesFrom(unprefixedResult)
}

private func properties(category: KsApi.Category) -> [String: Any] {
var result: [String: Any] = [:]

result["category_id"] = category.intID
result["category_name"] = category.name
result["category_projects_count"] = category.totalProjectCount

result["category_is_root"] = category.isRoot
result["category_root_id"] = category.rootId
result["category_root_name"] = category.root?.name

let parentProperties = category.parent.map(properties(category:)) ?? [:]
return result
Expand Down
Loading

0 comments on commit e3748d2

Please sign in to comment.