Pelacakan peristiwa di sisi klien secara umum terbagi menjadi tiga kategori:

  • Pelacakan berbasis kode
  • Pelacakan visual
  • Pelacakan otomatis

Artikel ini terutama memperkenalkan gagasan dan proses implementasi di balik pelacakan otomatis.

1. Pelacakan berbasis kode

Pelacakan berbasis kode berarti memanggil antarmuka pada setiap titik yang ingin dilacak dan langsung mengunggah data peristiwa. Kebanyakan layanan analitik pihak ketiga menyediakan api pelacakan berbasis kode yang praktis.

Namun, ini menimbulkan masalah: kode pelacakan tersebar di seluruh logika bisnis dan sangat terikat dengannya. Ketika layar atau alur bisnis berubah, tidak jelas apa yang harus dilakukan dengan peristiwa lama atau apakah peristiwa baru diperlukan. Seiring jumlah peristiwa bertambah, memelihara kode pelacakan yang tersebar menjadi mimpi buruk. Makro dan kelas pabrik dapat menyederhanakan kode, tetapi tidak mengubah masalah dasarnya.

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    // 埋点
    APE(kEvent4001);
}

2. Pelacakan visual

Pelacakan visual mengonfigurasi titik pengumpulan melalui alat visual. Klien mengurai konfigurasi dan melaporkan peristiwa secara otomatis, sehingga menghasilkan apa yang disebut “pelacakan tanpa jejak”. Salah satu solusi sumber terbuka yang mewakilinya adalah Mixpanel.

3. Pelacakan otomatis

Pelacakan otomatis, yang juga disebut pelacakan semua peristiwa, bukan berarti tidak ada instrumentasi. Sistem mengumpulkan dan melaporkan semua peristiwa, lalu server menyaring data yang berguna.

Sebagai optimasi lanjutan, server dapat mengirim file konfigurasi agar klien menyaring peristiwa sendiri.

Demi KPI, saya membuat ulang roda berdasarkan gagasan ini dan membangun WKTrackingData.

Di sini saya mencatat beberapa masalah dan gagasan dari implementasi WKTrackingData.

Gagasan implementasinya sederhana. Kodenya disusun sebagai berikut:

Arsitektur WKTrackingData asli: modul pengelola, jalur peristiwa, dan AOP

Di sini, WKTrackingDataManager menangani seluruh manajemen data dan konfigurasi pelacakan peristiwa.

Contoh penggunaan asli untuk konfigurasi pelacakan peristiwa

WKTrackingDataViewPathHelper menghasilkan nilai event_path.

Modul AOP bertanggung jawab melacak setiap peristiwa.

Untuk penggunaan terperinci, kunjungi GitHub.

Bagaimana sebuah peristiwa dapat dikenali secara unik?

Ada dua pertanyaan: bagaimana kita merepresentasikan peristiwa dan bagaimana memastikan keunikannya?

Merepresentasikan peristiwa

Peristiwa direpresentasikan dengan event_path. Untuk responder yang memicu peristiwa, gagasan utamanya adalah mengikuti rantai responder lalu membangun path rantai tersebut.

Hasil path responder tampak seperti ini:

"event_path" = "#buttonClick:#UIButton#UIButton[0]#UIView[0]#ViewController#...#UIApplication#AppDelegate
Mengenali peristiwa secara unik

Dalam beberapa skenario bisnis, button atau kontrol yang sama mewakili peristiwa bisnis berbeda ketika propertinya berubah.

Misalnya, button di beranda dapat menampilkan Ketuk untuk masuk ketika pengguna belum masuk, lalu Verifikasi identitas setelah masuk jika verifikasi belum selesai.

Untuk button yang sama, pohon tampilannya tidak berubah, sehingga path responder yang dihasilkan tetap sama.

Kasus serupa mencakup keadaan nyala/mati UISwitch, properti indexSelect pada UISegmentedControl, UIStepper, serta interaksi cell pada UITableView atau UICollectionView.

Untuk menanganinya, WKTrackingData membangun event_path dengan menambahkan properti kontrol secara selektif. event_path yang dihasilkan menjadi seperti ini:

"event_path" = "#buttonClick:#UIButton#UIButton[0]#UIView[0]#ViewController#...#UIApplication#AppDelegate#currentTitle=Button#state=1#enabled=1#selected=0";
Ekstensi khusus bisnis

Pertimbangkan skenario lain: karusel banner di beranda.

Setiap penempatan banner memiliki gambar dan url tujuan yang disediakan server, sedangkan posisinya dapat dikonfigurasi.

Di sini, banner pada setiap index tidak memiliki tujuan tetap. Peristiwa di posisi 0 tidak dapat ditentukan hanya dari event_path.

Untuk mengenali peristiwa secara unik, kita perlu menambahkan parameter khusus bisnis seperti url.

WKTrackingData juga mendukung ekstensi parameter bisnis, sehingga pemanggil dapat menambahkan parameter khusus:

Contoh kode asli yang memperluas peristiwa dengan parameter bisnis

Kontrol yang tidak perlu dilacak dapat dikecualikan menggunakan wk_ignoreTracking:

self.slider.wk_ignoreTracking = YES;

Masalah lain

Untuk melacak peristiwa berbeda, WKTrackingData menggunakan pendekatan berorientasi aspek dan memakai runtime untuk menukar metode secara langsung.

Namun, untuk melacak UIAlertView, UIActionSheet, UITableView, dan UICollectionView, kita perlu menukar metode delegate mereka.

  • Jika delegate class sudah mengimplementasikan metode tersebut, cukup tukar metodenya.

  • Jika delegate class belum mengimplementasikannya dan kita tetap ingin melacak peristiwa, kita perlu menambahkan implementasi delegate method yang sesuai secara manual.

- (void)wk_swizzleInstanceSelector:(SEL)origSel_ fromClass:(Class)fromClass replaceSelector:(SEL)replaceSel_ originNotImp:(SEL)notImpSel_ {
    Method originalMethod = class_getInstanceMethod([self class], origSel_);
    if (originalMethod) {
        [self wk_swizzleInstanceSelector:origSel_ fromClass:fromClass replaceSelector:replaceSel_];
    } else {
        Method notImpMethod = class_getInstanceMethod(fromClass, notImpSel_);
        // 如果delegateClass没有实现 origSel_ 方法
        // 则给delegateClass的 origSel_ 添加 orginReplaceMethod 的实现
        BOOL didAddNotImpMethod =
        class_addMethod([self class],
                        origSel_,
                        method_getImplementation(notImpMethod),
                        method_getTypeEncoding(notImpMethod));
        if (didAddNotImpMethod) {
            NSLog(@"%@ did add not imp method %@" , NSStringFromClass([self class]) , NSStringFromSelector(notImpSel_));
        }
    }
}

Implementasinya ada di sini

Namun dalam praktik, pada UITableView dan UICollectionView, ketika objek delegate tidak mengimplementasikan metode, menambahkan tableView:didSelectRowAtIndexPath: secara manual dengan implementation tetap tidak membuatnya terpanggil.

Pertama, lihat tumpukan pemanggilan normal tableView:didSelectRowAtIndexPath::

Tumpukan panggilan debugger asli untuk pemilihan baris table-view

Di sini, UITableView memanggil empat metode berikut secara berurutan untuk merespons ketukan cell:

  • 1. [UITableView _userSelectRowAtPendingSelectionIndexPath:]
  • 2. [UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:]
  • 3. [UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:isCellMultiSelect:]
  • 4. [TableViewController tableView:didSelectRowAtIndexPath:]

Urutan panggilan menunjukkan bahwa UITableView memanggil metode tableView:didSelectRowAtIndexPath: milik delegate class hanya setelah terlebih dahulu memanggil metodenya sendiri, _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:isCellMultiSelect:.

Pasang breakpoint pada _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:isCellMultiSelect: dan periksa assembly:

Tampilan assembly asli yang menunjukkan cabang metode delegate

Jika delegate class mengimplementasikan tableView:didSelectRowAtIndexPath:, semuanya berjalan dan panggilan tableView:didSelectRowAtIndexPath: selesai.

Namun jika delegate class tidak mengimplementasikan tableView:didSelectRowAtIndexPath:, bahkan setelah menambahkan tableView:didSelectRowAtIndexPath: dengan implementation, sistem tidak mencoba merespons tableView:didSelectRowAtIndexPath:.

Menelusuri assembly menunjukkan lompatan jump langsung ke instruksi lain.

WKTrackingData mengambil pendekatan berbeda dengan menukar [UITableView _userSelectRowAtPendingSelectionIndexPath:] secara langsung (pendekatan serupa digunakan untuk UICollectionView). Dengan demikian, interaksi UITableView dan UICollectionView tetap dapat dilacak ketika objek delegate tidak mengimplementasikan metode peristiwa cell terkait.

4. Penutup

Beberapa nilai event_path untuk peristiwa yang sama

Pertimbangkan beberapa versi rilis dengan sedikit perbedaan layar. Peristiwa yang sama kemudian dapat memiliki beberapa nilai event_path.

Dalam praktik, pemetaan ini memerlukan kerja sama rekan sisi server. Pemetaan dapat dibuat agar dapat dikonfigurasi di backend.

Mengoptimalkan analitik peristiwa

Bagian ekstensi khusus bisnis menjelaskan penambahan parameter bisnis. WKTrackingData menerapkannya melalui kategori.

Dalam praktik, pelacakan semua peristiwa membuang banyak bandwidth. Banyak peristiwa sebenarnya tidak diperlukan [(ŏ_ŏ)].

Optimasi lebih lanjut adalah meminta server mengirim file konfigurasi yang mencantumkan semua peristiwa yang ingin dilaporkan. Hanya event_path yang cocok dengan konfigurasi yang diunggah.

Pada tahap ini, parameter bisnis juga dapat diambil tanpa WKTrackingData: gunakan kvc secara langsung.

Contohnya:

key_path = "viewController.banner.url"

Jika Anda membaca sampai sini, buka WKTrackingData dan beri bintang. Jika ada pertanyaan, buka issue di GitHub atau tinggalkan komentar di bawah!