Skip to content

Commit

Permalink
Add scroll changed event
Browse files Browse the repository at this point in the history
  • Loading branch information
matus-tomlein committed Dec 12, 2023
1 parent 9e79e34 commit cb4a970
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 6 deletions.
13 changes: 11 additions & 2 deletions Sources/Core/ScreenViewTracking/ScreenSummaryState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,18 @@ class ScreenSummaryState: State {
var backgroundSeconds: TimeInterval = 0
var lastItemIndex: Int?
var itemsCount: Int?
var maxYOffset: Int?
var contentHeight: Int?

var data: [String: Any] {
var data: [String: Any] = [
"foreground_sec": foregroundSeconds,
"background_sec": backgroundSeconds
"foreground_sec": round(foregroundSeconds * 100) / 100,
"background_sec": round(backgroundSeconds * 100) / 100
]
if let lastItemIndex = lastItemIndex { data["last_item_index"] = lastItemIndex }
if let itemsCount = itemsCount { data["items_count"] = itemsCount }
if let maxYOffset = maxYOffset { data["max_y_offset"] = maxYOffset }
if let contentHeight = contentHeight { data["content_height"] = contentHeight }
return data
}

Expand Down Expand Up @@ -60,5 +64,10 @@ class ScreenSummaryState: State {
self.itemsCount = max(totalItems, self.itemsCount ?? 0)
}
}

func updateWithScrollChanged(_ event: ScrollChanged) {
maxYOffset = max(event.yOffset, maxYOffset ?? 0)
contentHeight = max(event.contentHeight, contentHeight ?? 0)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class ScreenSummaryStateMachine: StateMachineProtocol {
}

var subscribedEventSchemasForTransitions: [String] {
return [kSPScreenViewSchema, kSPScreenEndSchema, kSPForegroundSchema, kSPBackgroundSchema, kSPListItemViewSchema]
return [kSPScreenViewSchema, kSPScreenEndSchema, kSPForegroundSchema, kSPBackgroundSchema, kSPListItemViewSchema, kSPScrollChangedSchema]
}

var subscribedEventSchemasForEntitiesGeneration: [String] {
Expand All @@ -38,7 +38,7 @@ class ScreenSummaryStateMachine: StateMachineProtocol {
}

var subscribedEventSchemasForFiltering: [String] {
return [kSPListItemViewSchema, kSPScreenEndSchema]
return [kSPListItemViewSchema, kSPScrollChangedSchema, kSPScreenEndSchema]
}

func eventsBefore(event: Event) -> [Event]? {
Expand All @@ -59,6 +59,8 @@ class ScreenSummaryStateMachine: StateMachineProtocol {
state.updateForScreenEnd()
case let itemView as ListItemView:
state.updateWithListItemView(itemView)
case let scrollChanged as ScrollChanged:
state.updateWithScrollChanged(scrollChanged)
default:
break
}
Expand All @@ -82,7 +84,7 @@ class ScreenSummaryStateMachine: StateMachineProtocol {
if event.schema == kSPScreenEndSchema {
return state != nil
}
// do not track list item view events
// do not track list item view or scroll changed events
return false
}

Expand Down
1 change: 1 addition & 0 deletions Sources/Core/TrackerConstants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ let ecommercePageSchema = "iglu:com.snowplowanalytics.snowplow.ecommerce/page/js
let kSPScreenEndSchema = "iglu:com.snowplowanalytics.mobile/screen_end/jsonschema/1-0-0"
let kSPScreenSummarySchema = "iglu:com.snowplowanalytics.mobile/screen_summary/jsonschema/1-0-0"
let kSPListItemViewSchema = "iglu:com.snowplowanalytics.mobile/list_item_view/jsonschema/1-0-0"
let kSPScrollChangedSchema = "iglu:com.snowplowanalytics.mobile/scroll_changed/jsonschema/1-0-0"

// --- Event Keys
let kSPEventPageView = "pv"
Expand Down
5 changes: 5 additions & 0 deletions Sources/Snowplow/Events/ListItemView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,16 @@ public class ListItemView: SelfDescribingAbstract {
/// Total number of items in the list
public var itemsCount: Int?

/// - Parameters:
/// - index: Index of the item in the list
@objc
public init(index: Int) {
self.index = index
}

/// - Parameters:
/// - index: Index of the item in the list
/// - totalItems: Total number of items in the list
@objc
public init(index: Int, totalItems: Int) {
self.index = index
Expand Down
47 changes: 47 additions & 0 deletions Sources/Snowplow/Events/ScrollChanged.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright (c) 2013-2023 Snowplow Analytics Ltd. All rights reserved.
//
// This program is licensed to you under the Apache License Version 2.0,
// and you may not use this file except in compliance with the Apache License
// Version 2.0. You may obtain a copy of the Apache License Version 2.0 at
// http://www.apache.org/licenses/LICENSE-2.0.
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the Apache License Version 2.0 is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the Apache License Version 2.0 for the specific
// language governing permissions and limitations there under.

import Foundation

/// Event tracked when a scroll view's scroll position changes.
/// If screen engagement tracking is enabled, the scroll changed events will be aggregated into a `screen_summary` entity.
///
/// Schema: `iglu:com.snowplowanalytics.mobile/scroll_changed/jsonschema/1-0-0`
@objc(SPScrollChanged)
public class ScrollChanged: SelfDescribingAbstract {
/// Vertical scroll offset in pixels
@objc
public var yOffset: Int
/// The height of the scroll view content in pixels
public var contentHeight: Int

/// - Parameters:
/// - yOffset: Vertical scroll offset in pixels
/// - contentHeight: The height of the scroll view content in pixels
@objc
public init(yOffset: Int, contentHeight: Int) {
self.yOffset = yOffset
self.contentHeight = contentHeight
}

override var schema: String {
return kSPScrollChangedSchema
}

override var payload: [String : Any] {
return [
"y_offset": yOffset,
"content_height": contentHeight
]
}
}
23 changes: 23 additions & 0 deletions Tests/ScreenViewTracking/TestScreenSummaryStateMachine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,29 @@ class TestScreenSummaryStateMachine: XCTestCase {

wait(for: [expectScreenEnd], timeout: 10)
}

func testUpdatesScrollMetrics() {
let expectScreenEnd = expectation(description: "Screen end event")

let eventSink = EventSink { event in
if event.schema == kSPScreenEndSchema {
let entity = event.entities.first { $0.schema == kSPScreenSummarySchema }
XCTAssertEqual((entity?.data as? [String: Any])?["max_y_offset"] as? Int, 30)
XCTAssertEqual((entity?.data as? [String: Any])?["content_height"] as? Int, 100)
expectScreenEnd.fulfill()
}
}

let tracker = createTracker([eventSink])

_ = tracker.track(ScreenView(name: "Screen 1"))
_ = tracker.track(ScrollChanged(yOffset: 10, contentHeight: 100))
_ = tracker.track(ScrollChanged(yOffset: 30, contentHeight: 100))
_ = tracker.track(ScrollChanged(yOffset: 20, contentHeight: 100))
_ = tracker.track(ScreenView(name: "Screen 2"))

wait(for: [expectScreenEnd], timeout: 10)
}

private func createTracker(_ configurations: [ConfigurationProtocol]) -> TrackerController {
let networkConfig = NetworkConfiguration(networkConnection: MockNetworkConnection(requestOption: .post, statusCode: 200))
Expand Down

0 comments on commit cb4a970

Please sign in to comment.