Slide 1

Slide 1 text

AbemaTV, Inc. All Rights Reserved
 AbemaTV, Inc. All Rights Reserved
 1 SwiftUI 移行のための インプレッション トラッキング基盤の構築 2025 March 3rd Koki Hirokawa

Slide 2

Slide 2 text

AbemaTV, Inc. All Rights Reserved
 現状 2 ● UIKit が支配的 UIKit SwiftUI

Slide 3

Slide 3 text

AbemaTV, Inc. All Rights Reserved
 SwiftUI への移行 3 SwiftUI ● 新規実装は SwiftUI 主体 ● UIKit はスポット利用 UIKit

Slide 4

Slide 4 text

AbemaTV, Inc. All Rights Reserved
 移行における課題 4 ● キャッチアップ ● iOS 15.0 までのサポート ● インプレッショントラッキングの仕組み

Slide 5

Slide 5 text

AbemaTV, Inc. All Rights Reserved
 移行における課題 5 ● キャッチアップ ● iOS 15.0 までのサポート ● インプレッショントラッキング の仕組み ✔ ✔ ✔ ✔

Slide 6

Slide 6 text

AbemaTV, Inc. All Rights Reserved
 目次 6 ● 自己紹介 ● インプレッショントラッキングとは ● SwiftUI での基盤構築 ● 工夫した点 ● まとめ

Slide 7

Slide 7 text

AbemaTV, Inc. All Rights Reserved
 Koki Hirokawa ● 2020年 AbemaTV新卒入社 
 7 Profile @pihero13 KokiHirokawa

Slide 8

Slide 8 text

AbemaTV, Inc. All Rights Reserved
 インプレッショントラッキングとは 8

Slide 9

Slide 9 text

AbemaTV, Inc. All Rights Reserved
 行動ログ 9 ● ユーザの行動を分析し、ビジネス戦略の意思決定を行うためのログ ○ どの画面に遷移した ○ 何を視聴した ○ 何を見た ○ 何をクリックした

Slide 10

Slide 10 text

AbemaTV, Inc. All Rights Reserved
 インプレッションログ 10 ● 画面上に表示されるどの要素がユーザに見られたか ✔ ✔ ✔ ✔

Slide 11

Slide 11 text

AbemaTV, Inc. All Rights Reserved
 インプレッションログ 11 ✔ ✔ ✔ ✔ .onAppear { sendImpressionLog(id: “mylist-\(id)”) } ● シンプルな実装

Slide 12

Slide 12 text

AbemaTV, Inc. All Rights Reserved
 インプレッションログ 12 ✔ ✔ ✔ ✔ .onAppear { sendImpressionLog(id: “mylist-\(id)”) } ● 「見た」の定義はもう少し複雑 ❌

Slide 13

Slide 13 text

AbemaTV, Inc. All Rights Reserved
 インプレッションログ 13 ✔ ✔ ✔ ● 例) 要素の80%以上の領域が画面内に2秒以上 表示されたことを、ユーザが「見た」と定義する ✔

Slide 14

Slide 14 text

AbemaTV, Inc. All Rights Reserved
 SwiftUI での基盤構築 14

Slide 15

Slide 15 text

AbemaTV, Inc. All Rights Reserved
 前提 15 ● ABEMA では多くの画面がスクロール可能 ● UIKit では TableView や CollectionView で表示するコンテンツのインプレッション をトラッキングするための基盤を用意

Slide 16

Slide 16 text

AbemaTV, Inc. All Rights Reserved
 構成 16 ImpressionTrackingController Trackable ScrollView Trackable View

Slide 17

Slide 17 text

AbemaTV, Inc. All Rights Reserved
 利用イメージ 17 @StateObject var controller = ImpressionTrackingController( configuration: .init( minimumAreaRatio: 0.8, minimumDuration: 2 ) )

Slide 18

Slide 18 text

AbemaTV, Inc. All Rights Reserved
 利用イメージ 18 TrackableScrollView(showsIndicator: false) { LazyVStack { ForEach(fruits) { fruit in FruitView(fruit) .trackable(id: fruit.id) { sendImpressionLog() } } } } .environment(\.trackingController, controller)

Slide 19

Slide 19 text

AbemaTV, Inc. All Rights Reserved
 Trackable ScrollView - RootViewFrame のキャッシュ 19 ImpressionTrackingController Trackable ScrollView .onChange( geometry.frame(in: .global) ) { frame in controller.setRootViewFrame(frame) }

Slide 20

Slide 20 text

AbemaTV, Inc. All Rights Reserved
 Trackable ScrollView - スクロールの検知 20 ImpressionTrackingController Trackable ScrollView .onChange( geometry.frame(in: .named(space)).origin ) { origin in if origin != prevOrigin { controller.sendScrollEvent() } }

Slide 21

Slide 21 text

AbemaTV, Inc. All Rights Reserved
 21 Trackable View - インプレッションのロジック Trackable View .onReceive(controller.didScroll) { let visibility = … if 0.8 <= visibility { // タイマーを設定 () } else { // タイマーを停止 () } } ImpressionTrackingController

Slide 22

Slide 22 text

AbemaTV, Inc. All Rights Reserved
 22 Trackable View - 条件を満たした場合 Trackable View .onReceive(controller.didTrack) { // ログ送信 } ImpressionTrackingController

Slide 23

Slide 23 text

AbemaTV, Inc. All Rights Reserved
 利用イメージ 23 FruitView(fruit) .trackable(id: fruit.id) { sendImpressionLog() }

Slide 24

Slide 24 text

AbemaTV, Inc. All Rights Reserved
 工夫した点 24

Slide 25

Slide 25 text

AbemaTV, Inc. All Rights Reserved
 デバッグ画面 25 ● 参考実装も兼ねたデモ画面

Slide 26

Slide 26 text

AbemaTV, Inc. All Rights Reserved
 デバッグ画面 26 ● 必ず実機でも確認する ○ シミュレータと実機で挙動が変わることがあるため注意 ● OS Major Version も網羅しておくと安心

Slide 27

Slide 27 text

AbemaTV, Inc. All Rights Reserved
 UI Test 27 ● 想像以上に実行時間が長い

Slide 28

Slide 28 text

AbemaTV, Inc. All Rights Reserved
 UI Test 28 ● 想像以上に実行時間が長い ○ 表示内容の検証をしている間に指定した インプレッションの秒数を超える

Slide 29

Slide 29 text

AbemaTV, Inc. All Rights Reserved
 UI Test 29 ● 想像以上に実行時間が長い ○ 表示内容の検証をしている間に指定した インプレッションの秒数を超える ■ 1秒から3秒に変更

Slide 30

Slide 30 text

AbemaTV, Inc. All Rights Reserved
 UI Test 30 ● ボタンをタップできずテストが失敗

Slide 31

Slide 31 text

AbemaTV, Inc. All Rights Reserved
 UI Test 31 ● ボタンをタップできずテストが失敗 ○ タップ可能になるまで待機 try await app.buttons[“Scroll to Bottom”] .abema.tapOnHittable()

Slide 32

Slide 32 text

AbemaTV, Inc. All Rights Reserved
 UI Test 32 ● 固定量のスクロールができない

Slide 33

Slide 33 text

AbemaTV, Inc. All Rights Reserved
 UI Test 33 ● 固定量のスクロールができない ○ 慣性スクロールが働く ○ デバッグ画面では最下部までスクロールするためのボタンを追加

Slide 34

Slide 34 text

AbemaTV, Inc. All Rights Reserved
 デバッグ機能 34 ● Environment Variables ● トラッキング対象にオーバーレイ を配置し、視覚的にデバッグ

Slide 35

Slide 35 text

AbemaTV, Inc. All Rights Reserved
 まとめ 35

Slide 36

Slide 36 text

AbemaTV, Inc. All Rights Reserved
 まとめ 36 ● SwiftUI 主体の実装へ移行するにあたって、インプレッションログを送信するための基 盤を構築 ● TrackableScrollView や trackable modifier を用意することで、実装コストを抑えてイ ンプレッションログの送信ができるように ● UI Test のメリットは大きいものの、実装・運用コストは少し高め

Slide 37

Slide 37 text

AbemaTV, Inc. All Rights Reserved
 ご清聴ありがとうございました 37