کلائنٹ کی طرف ایونٹ ٹریکنگ عمومی طور پر تین اقسام میں آتی ہے:
- کوڈ پر مبنی ٹریکنگ
- بصری ٹریکنگ
- خودکار ٹریکنگ
یہ مضمون بنیادی طور پر خودکار ٹریکنگ کے خیال اور نفاذ کے عمل کا تعارف ہے۔
1. کوڈ پر مبنی ٹریکنگ
کوڈ پر مبنی ٹریکنگ کا مطلب ہر مطلوبہ مقام پر انٹرفیس بلا کر ایونٹ ڈیٹا براہِ راست اپ لوڈ کرنا ہے۔ زیادہ تر فریقِ ثالث تجزیاتی خدمات آسان کوڈ ٹریکنگ api دیتی ہیں۔
مگر اس سے مسئلہ پیدا ہوتا ہے: ٹریکنگ کوڈ کاروباری منطق میں پھیلا اور اس سے مضبوطی سے جڑا ہوتا ہے۔ اسکرین یا کاروباری بہاؤ بدلنے پر پرانے ایونٹ کا عمل اور نئے کی ضرورت غیر واضح ہوتی ہے۔ تعداد بڑھنے پر بکھرے کوڈ کی دیکھ بھال مشکل بن جاتی ہے۔ میکرو اور فیکٹری کلاس کوڈ مختصر کر سکتے ہیں، بنیادی مسئلہ نہیں بدلتے۔
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
// 埋点
APE(kEvent4001);
}
2. بصری ٹریکنگ
بصری ٹریکنگ بصری ٹول سے جمع کرنے کے مقامات ترتیب دیتی ہے۔ کلائنٹ ترتیب خود پڑھ کر ایونٹ رپورٹ کرتا ہے، جسے ”بے نشان ٹریکنگ“ کہا جاتا ہے۔ ایک معروف اوپن سورس حل Mixpanel ہے۔
3. خودکار ٹریکنگ
خودکار یا تمام ایونٹ ٹریکنگ کا مطلب واقعی بغیر instrumentation نہیں۔ یہ تمام ایونٹ جمع و رپورٹ کرتی اور مفید ڈیٹا چھانٹنے کا کام سرور کو دیتی ہے۔
مزید بہتری میں سرور ترتیب فائل بھیج سکتا ہے تاکہ کلائنٹ خود ایونٹ چھانٹے۔
KPI کے لیے، میں نے اسی خیال پر پہیہ دوبارہ ایجاد کیا اور WKTrackingData بنایا۔
یہاں WKTrackingData کے نفاذ میں پیش آنے والے مسائل اور خیالات درج ہیں۔
نفاذ کا خیال سادہ ہے۔ کوڈ یوں منظم ہے:

یہاں، WKTrackingDataManager تمام ڈیٹا انتظام اور ایونٹ ٹریکنگ ترتیب سنبھالتا ہے۔

WKTrackingDataViewPathHelper، event_path قدر بناتا ہے۔
AOP ماڈیول ہر ایونٹ کی ٹریکنگ کا ذمہ دار ہے۔
تفصیلی استعمال کے لیے GitHub دیکھیں۔
ایونٹ کی منفرد شناخت کیسے ہو؟
دو سوال ہیں: ایونٹ کیسے ظاہر کریں اور اس کی انفرادیت کیسے یقینی بنائیں؟
ایونٹ کی نمائندگی
ایونٹ event_path سے ظاہر ہوتے ہیں۔ ایونٹ چلانے والے responder کے لیے بنیادی خیال اس کی responder chain کی پیروی کر کے اس کا path بنانا ہے۔
نتیجے کا responder path یوں ہے:
"event_path" = "#buttonClick:#UIButton#UIButton[0]#UIView[0]#ViewController#...#UIApplication#AppDelegate
ایونٹ کی منفرد شناخت
کچھ کاروباری حالات میں ایک ہی button یا کنٹرول خصوصیات بدلنے پر مختلف ایونٹ ظاہر کرتا ہے۔
مثلاً ہوم button سائن آؤٹ پر سائن ان کے لیے ٹیپ اور سائن ان کے بعد نامکمل تصدیق پر شناخت کی تصدیق دکھا سکتا ہے۔
اسی button کی view tree نہیں بدلی، اس لیے بنا ہوا responder path یکساں رہتا ہے۔
ایسی مثالوں میں UISwitch کی آن/آف حالت، UISegmentedControl کا indexSelect، UIStepper، اور UITableView یا UICollectionView کے cell تعامل شامل ہیں۔
اس کے لیے WKTrackingData کنٹرول کی منتخب خصوصیات event_path میں شامل کرتا ہے۔ نتیجے کا event_path یوں ہے:
"event_path" = "#buttonClick:#UIButton#UIButton[0]#UIView[0]#ViewController#...#UIApplication#AppDelegate#currentTitle=Button#state=1#enabled=1#selected=0";
کاروبار کے مخصوص اضافے
ایک اور صورت: ہوم اسکرین banner carousel۔
ہر banner جگہ کی تصویر اور منزل url سرور دیتا ہے، اور مقامات قابلِ ترتیب ہیں۔
ہر index پر banner کی منزل مقرر نہیں۔ مقام 0 کا ایونٹ صرف event_path سے معلوم نہیں ہو سکتا۔
منفرد شناخت کے لیے url جیسے کاروباری پیرامیٹر شامل کرنا ہوں گے۔
WKTrackingData کاروباری پیرامیٹر اضافے بھی دیتا ہے، تاکہ caller مخصوص پیرامیٹر شامل کرے:

جن کنٹرولز کو ٹریک نہ کرنا ہو انہیں wk_ignoreTracking سے خارج کریں:
self.slider.wk_ignoreTracking = YES;
دیگر مسائل
مختلف ایونٹ کے لیے WKTrackingData aspect-oriented طریقہ اپناتا اور runtime سے براہِ راست طریقے swizzle کرتا ہے۔
ٹریکنگ کے لیے UIAlertView، UIActionSheet، UITableView اور UICollectionView کے delegate طریقے swizzle کرنا ضروری ہیں۔
اگر
delegate classپہلے طریقہ نافذ کرتی ہے تو اسے سیدھا swizzle کریں۔اگر
delegate classنے نافذ نہیں کیا اور پھر بھی ٹریک کرنا ہو تو متعلقہdelegate methodکا نفاذ دستی طور پر شامل کریں۔
- (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_));
}
}
}
عملی طور پر UITableView اور UICollectionView کے delegate objects نے طریقہ نافذ نہ کیا ہو تو tableView:didSelectRowAtIndexPath: کا implementation دستی طور پر شامل کرنے پر بھی یہ نہیں چلتا۔
پہلے معمول کا tableView:didSelectRowAtIndexPath: call stack دیکھیں:

یہاں، UITableView، cell ٹیپ کے جواب میں یہ چار طریقے ترتیب سے بلاتا ہے:
- 1. [UITableView _userSelectRowAtPendingSelectionIndexPath:]
- 2. [UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:]
- 3. [UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:isCellMultiSelect:]
- 4. [TableViewController tableView:didSelectRowAtIndexPath:]
ترتیب سے واضح ہے کہ UITableView، delegate class کا tableView:didSelectRowAtIndexPath: بلانے سے پہلے اپنا _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:isCellMultiSelect: چلاتا ہے۔
اس طریقے پر _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:isCellMultiSelect: breakpoint لگا کر assembly دیکھیں:

اگر delegate class نے tableView:didSelectRowAtIndexPath: نافذ کیا ہو تو سب درست اور tableView:didSelectRowAtIndexPath: call مکمل ہوتا ہے۔
مگر delegate class نے tableView:didSelectRowAtIndexPath: نافذ نہ کیا ہو تو tableView:didSelectRowAtIndexPath: کا implementation دستی طور پر شامل کرنے کے باوجود tableView:didSelectRowAtIndexPath: کے جواب کی کوشش نہیں ہوتی۔
assembly کی پیروی براہِ راست دوسری instruction تک jump دکھاتی ہے۔
WKTrackingData مختلف طریقہ لیتا اور [UITableView _userSelectRowAtPendingSelectionIndexPath:] کو براہِ راست swizzle کرتا ہے (UICollectionView کے لیے بھی ملتا جلتا طریقہ)۔ یوں UITableView اور UICollectionView کے delegate object میں متعلقہ cell event طریقہ نہ ہونے پر بھی تعامل ٹریک ہوتے ہیں۔
4. اختتامی باتیں
ایک ایونٹ کے لیے متعدد event_path قدریں
تھوڑی مختلف اسکرینوں والے متعدد جاری نسخوں میں ایک ایونٹ کے کئی event_path ہو سکتے ہیں۔
عملی طور پر اس mapping کے لیے سرور ساتھیوں کا تعاون چاہیے۔ اسے backend میں قابلِ ترتیب بنایا جا سکتا ہے۔
ایونٹ تجزیات بہتر کرنا
اوپر کاروبار کے مخصوص اضافے میں پیرامیٹر شامل کرنا بیان ہوا۔ WKTrackingData اسے categories سے نافذ کرتا ہے۔
عملی طور پر تمام ایونٹ ٹریکنگ نے بہت bandwidth ضائع کی۔ بہت سے ایونٹ غیر ضروری تھے [(ŏ_ŏ)]۔
مزید بہتری میں سرور مطلوبہ تمام ایونٹ کی ترتیب فائل بھیجے۔ صرف ترتیب سے ملتا event_path اپ لوڈ ہو۔
اب کاروباری پیرامیٹر WKTrackingData کے بغیر بھی لیے جا سکتے ہیں: براہِ راست kvc استعمال کریں۔
مثلاً:
key_path = "viewController.banner.url"
یہاں تک پڑھ لیا تو WKTrackingData کھول کر star دیں۔ سوال ہو تو GitHub پر issue بنائیں یا نیچے تبصرہ چھوڑیں!