למה אפליקציה אחת צריכה שני כלי מדידה?
AppsFlyer הוא פלטפורמת ייחוס מובייל (MMP). התפקיד שלו הוא לקבוע לאיזה מקור מדיה שייכת כל התקנה, לפי קליק או צפייה בחלון ייחוס מוגדר. ברירת המחדל לפי התיעוד היא 7 ימים לקליק ו-24 שעות לצפייה. מה שקורה מחוץ לחלון נחשב אורגני. AppsFlyer גם מחזיר פוסטבקים לרשתות הפרסום כדי שהאלגוריתמים שלהן ילמדו אילו משתמשים שווים יותר. בנוסף הוא מרכז את נתוני SKAdNetwork ב-iOS.
Firebase Analytics הוא כלי אנליטיקת מוצר. ה-SDK אוסף אירועים אוטומטיים כמו first_open, screen_view ו-in_app_purchase, מאפשר להגדיר עד 500 אירועים שונים לפי התיעוד, בונה קהלים ומייצא ל-BigQuery. הנתונים מופיעים גם בקונסולת Firebase וגם ב-GA4, כי זרם האפליקציה ב-GA4 הוא אותו SDK. בייחוס, Firebase יודע לזהות מקורות של Google: קליקים מ-Google Ads באנדרואיד, Google Play install referrer, קישורי UTM ו-Apple Search Ads דרך AdServices. הוא לא מחליף MMP מול רשתות כמו Meta, TikTok או רשתות משחקים.
בפרויקטים שלנו הטענה החוזרת היא "יש לנו Firebase, למה לשלם על AppsFlyer", או להפך, "יש לנו AppsFlyer, למה להתעסק עם GA4". התשובה היא ששני הכלים עונים על שאלות שונות. הבעיה מתחילה כשמנסים לקבל את אותה תשובה משניהם, או כששולחים את אותו אירוע לשניהם ואז מחברים את המספרים.
איזה כלי עונה על איזו שאלה עסקית?
הטבלה הבאה היא מיפוי השימושים שאנחנו מכינים לכל לקוח לפני שכותבים שורת קוד אחת. הכלל פשוט: כל שאלה מקבלת כלי אחד שעונה עליה. הכלי השני משמש להצלבה בלבד.
| השאלה העסקית | הכלי שעונה | למה |
|---|---|---|
| כמה התקנות הגיעו מכל רשת פרסום וקמפיין? | AppsFlyer | ייחוס last-touch מול כל הרשתות, חלונות ייחוס לפי מקור, התמודדות עם SKAN ב-iOS |
| מה ה-ROAS של קמפיין ברשת מסוימת? | AppsFlyer | ההכנסה (af_revenue או ROI360) מחוברת למקור ההתקנה. GA4 לא רואה את רשתות הצד השלישי |
| איזה אירועים לשלוח לרשתות לאופטימיזציה? | AppsFlyer | פוסטבקים לרשתות הם תפקיד של MMP. GA4 שולח המרות רק ל-Google Ads |
| מה המשתמשים עושים בין ההתקנה לרכישה? | Firebase / GA4 | screen_view, משפכים, Path exploration, פרמטרים לאירוע, חיתוך לפי מאפייני משתמש |
| כמה משתמשים חוזרים אחרי 7 ו-30 יום? | Firebase / GA4 | דוחות שימור וקוהורטות מובנים, מבוססים על app_instance_id ו-user_id |
| איזה קהל לשלוח לו הודעת פוש או Remote Config? | Firebase | קהלים של Firebase מחוברים ישירות ל-FCM, Remote Config ו-A/B Testing |
| כמה ניסיונות הפכו למנוי בתשלום וכמה חודשו? | שניהם, כל אחד לתפקידו | GA4 אוסף אוטומטית app_store_subscription_convert ו-renew. AppsFlyer עם ROI360 מקבל אותם מהחנויות ומחבר למקור המדיה |
| איך קמפיין בגוגל השפיע על התנהגות בתוך האפליקציה? | GA4 עם קישור Google Ads | Auto-tagging באנדרואיד, קהלי GA4 ל-Google Ads. ב-iOS אין auto-tagging להתקנות |
| ניתוח גולמי ברמת האירוע ב-SQL | GA4 דרך BigQuery | ייצוא יומי של כל האירועים, כולל אלה שהגיעו מ-AppsFlyer דרך האינטגרציה |
מי מודד כל שלב במסע המשתמש?
הדיאגרמה מתארת מסע של אפליקציה עם ניסיון חינם ומנוי. למטה חמשת השלבים, מעליהם מה AppsFlyer מודד בכל שלב ומעליו מה Firebase / GA4 מודד. השמות בדיאגרמה הם אלה שמופיעים במילון האירועים בסעיף הבא.
מי מודד מה
מי מודד כל שלב במסע המשתמש
installייחוס למקור מדיהfirst_openאוטומטי, מקור מהפוסטבקaf_complete_registration פוסטבק לרשתותsign_upמומלץ, פרמטר methodaf_start_trial אירוע מוגדר מראשstart_trial מותאם, אין אירוע מומלץaf_purchase af_revenue או ROI360in_app_purchase אוטומטי מהחנותaf_ars_subscription_renewed ROI360 מהחנותapp_store_subscription_renew אוטומטי, אירוע מפתחapp_instance_id . הוא מצרף את הייחוס ל-first_open של Firebase ולא יוצר אירוע חדש. כל אירוע של Firebase נשלח פעם אחת בלבד: מה-SDK של Firebase או מהחנות, לא גם מ-AppsFlyer.איך בונים מילון אירועים אחיד לשני הכלים?
הבעיה הנפוצה ביותר שאנחנו רואים היא שני מילוני אירועים נפרדים: המפתח מימש "purchase" ב-Firebase, "Purchase" ב-AppsFlyer ומישהו אחר הוסיף "af_purchase" חצי שנה אחרי. התיקון הוא מסמך אחד שבו לכל שלב במסע יש שם אירוע ב-AppsFlyer עם קידומת af_, שם אירוע ב-GA4 לפי רשימת האירועים המומלצים של Google. לשני השמות מצרפים את אותם פרמטרים עסקיים. הטבלה הבאה היא דוגמה לאפליקציית מנוי עם ניסיון חינם.
| שלב | AppsFlyer | GA4 / Firebase | פרמטרים משותפים | מי שולח ולמי |
|---|---|---|---|---|
| התקנה | install (נוצר אוטומטית ב-SDK) | first_open (אוטומטי) | אין. הייחוס מגיע מהפוסטבק של AppsFlyer | שני ה-SDK, בלי קוד נוסף |
| הרשמה | af_complete_registration | sign_up | method (email, google, apple) | הקוד שולח לשניים. לא ממפים את af_complete_registration לפוסטבק ל-GA4 |
| התחברות | af_login | login | method | כמו הרשמה |
| תחילת ניסיון | af_start_trial | start_trial (מותאם, אין אירוע מומלץ) | af_content_id / item_id, trial_days | הקוד שולח לשניים אחרי אישור החנות |
| רכישה ראשונה | af_purchase עם af_revenue, af_currency, af_content_id, af_receipt_id. עם ROI360 לא שולחים כלל | in_app_purchase (אוטומטי). purchase ידני רק אם האוטומטי לא זמין | value / af_revenue, currency / af_currency, transaction_id / af_receipt_id | לכל כלי מסלול אחד. GA4 מזהיר שאוטומטי וידני יחד יוצרים כפילות |
| המרה מניסיון למנוי | af_ars_trial_converted (ROI360, מהחנות) | app_store_subscription_convert (אוטומטי, אירוע מפתח) | product_id, price, currency | החנויות בלבד. בלי ROI360 שולחים af_subscribe מהקוד פעם אחת |
| חידוש | af_ars_subscription_renewed (ROI360) | app_store_subscription_renew (אוטומטי, renewal_count) | product_id, price | החנויות בלבד. אין קוד בצד האפליקציה |
| ביטול / זיכוי | af_ars_subscription_canceled, af_purchase_refund | app_store_subscription_cancel, app_store_refund (אנדרואיד בלבד) | product_id | החנויות. ב-iOS GA4 לא אוסף ביטול וזיכוי אוטומטית |
שלוש הערות לטבלה. ראשית, ב-GA4 אין אירוע מומלץ לתחילת ניסיון. לכן start_trial הוא אירוע מותאם שמגדירים כאירוע מפתח ידנית. שנית, השמות השמורים של Google, בהם first_open, session_start, in_app_purchase ו-app_install, אסורים לשימוש בפוסטבקים מ-AppsFlyer. שלישית, ב-AppsFlyer הפרמטר היחיד שנספר כהכנסה בדוחות הוא af_revenue. לקוחות ROI360 מתבקשים בתיעוד לא להשתמש בו בכלל כדי לא לספור הכנסה פעמיים.
איך מחברים בין AppsFlyer ל-GA4 בלי לספור פעמיים?
האינטגרציה הרשמית עובדת בכיוון אחד: AppsFlyer שולח פוסטבקים ל-GA4 ומזהה את המשתמש לפי app_instance_id של Firebase. התיעוד של AppsFlyer קובע במפורש ש-GA4 לא מבצע דה-דופליקציה בין אירועים שהגיעו מה-SDK של Firebase לאירועים שהגיעו מ-AppsFlyer. לכן עיקרון העבודה הוא: AppsFlyer מעביר ל-GA4 את מה שרק הוא יודע, כלומר את הייחוס. הוא לא מעביר את מה ש-GA4 כבר יודע בעצמו.
- מגדירים את חלוקת התפקידים. מסכימים עם הלקוח שהמספר הרשמי להתקנות לפי מקור הוא של AppsFlyer. המספר הרשמי להתנהגות, שימור ומשפכים הוא של GA4. כותבים את זה במסמך המדידה.
- המפתח מעביר ל-AppsFlyer את מזהי Firebase. בקוד האפליקציה שולפים את app_instance_id ואת ga_session_id מה-SDK של Firebase ומעבירים אותם ל-AppsFlyer דרך setAdditionalData (אנדרואיד, Unity, React Native) או customData (iOS), לפני ההפעלה הראשונה של ה-SDK. שני המזהים נשלחים בקריאה אחת, כי קריאה שנייה דורסת את הראשונה.
- מפעילים את האינטגרציה ב-Partner Marketplace. ב-AppsFlyer בוחרים Google Analytics 4, מזינים את Firebase App ID ואת ה-API Secret שנוצר ב-GA4 תחת זרם האפליקציה (אנדרואיד או iOS, לא זרם ווב). בפוסטבקים של ברירת המחדל בוחרים את כל מקורות המדיה כולל אורגני, כדי שגם התקנות אורגניות יקבלו ייחוס אחיד.
- ממפים לפוסטבק רק אירועים שה-SDK של Firebase לא שולח. במקרה הרגיל, כשהקוד כבר שולח sign_up ו-start_trial ישירות ל-Firebase, לא ממפים אף אירוע in-app. אם יש אירוע שקיים רק ב-AppsFlyer, למשל אירוע שמגיע מ-ROI360 מהחנות, ממפים אותו לשם GA4 שאינו שמור ושאינו קיים כבר, עם הפרמטרים החובה שהתיעוד דורש.
- בוחרים מסלול אחד להכנסה בכל כלי. ב-GA4: in_app_purchase אוטומטי, בלי purchase ידני על אותה עסקה. ב-AppsFlyer: af_purchase עם af_revenue מהקוד, או ROI360 מהחנות, לא שניהם.
בדיקת היגיון פשוטה בסוף התהליך: אם אירוע מופיע ב-GA4 פעמיים באותה שנייה, פעם עם מקור הפוסטבק ופעם מה-SDK, מישהו מיפה אירוע שלא היה צריך למפות. אם אירוע לא מופיע כלל, מזהי Firebase לא הועברו ל-AppsFlyer לפני ההפעלה הראשונה.
מה קורה ב-iOS עם ATT ו-SKAdNetwork?
מאז iOS 14.5 המזהה הפרסומי IDFA זמין רק למשתמש שאישר את חלון ה-ATT. למי שלא אישר, AppsFlyer מספק תוצאות ייחוס מצרפיות דרך הפוסטבקים של SKAdNetwork. הפוסטבקים האלה אנונימיים, לא ברמת המשתמש. הם נושאים Conversion Value שהמפרסם מגדיר ב-Conversion Studio. הם מגיעים באיחור: 24 עד 48 שעות בחלון הראשון של SKAN 4 ו-24 עד 144 שעות בחלונות השני והשלישי. התיעוד מסביר שאותה התקנה יכולה להופיע גם בלוח הייחוס הרגיל וגם בלוח SKAN. לפעמים היא תופיע כאורגנית באחד וכממומנת בשני. זה לא באג, זה שני מערכי מדידה שמשלימים זה את זה.
ההשלכה למדריך הזה היא ששלב ההתקנה ב-iOS הוא כולו של AppsFlyer. GA4 לא עובד עם SKAdNetwork, לא תומך ב-auto-tagging להתקנות iOS ומייחס ב-iOS בעיקר Apple Search Ads דרך AdServices וקישורי UTM. אירוע first_open ממשיך להיאסף גם בלי הסכמה, כי הוא לא דורש IDFA, אבל המקור שלו יהיה בדרך כלל ישיר. הפוסטבק של AppsFlyer ל-GA4 מצרף ייחוס רק למשתמשים שיש להם מזהה app_instance_id. לכן השוואת התקנות iOS בין שני הכלים תמיד תראה פער. את ההתנהגות שאחרי ההתקנה GA4 ממשיך למדוד כרגיל, עם או בלי ATT.
אילו טעויות נפוצות גורמות לספירה כפולה?
מיפוי af_purchase לפוסטבק purchase כשהחנות כבר שולחת in_app_purchase
זו הטעות הנפוצה ביותר. התוצאה היא שבדוח ההכנסות של GA4 כל עסקה מופיעה פעמיים, פעם כ-in_app_purchase ופעם כ-purchase. הפתרון הוא להסיר את המיפוי ולהשאיר את הפוסטבק להתקנות בלבד.
af_revenue בקוד יחד עם ROI360
ברגע שמפעילים את ROI360 store revenue, האירועים af_purchase ו-af_ars_ מגיעים מהחנויות. מי שהשאיר את af_purchase עם af_revenue בקוד מדווח כל הכנסה פעמיים ב-AppsFlyer. ה-ROAS שמוצג לרשתות שגוי.
אירוע חידוש מהקוד
חידוש מנוי מתרחש בשרת של אפל או גוגל, גם כשהאפליקציה סגורה. מי ששולח subscription_renewed מהקוד בפתיחה הבאה של האפליקציה מודד חידוש בתאריך שגוי ובנוסף לאירוע האוטומטי app_store_subscription_renew.
מזהי Firebase בשתי קריאות נפרדות
setAdditionalData עם app_instance_id ואחר כך setAdditionalData עם ga_session_id משאיר ב-AppsFlyer רק את המזהה השני. הפוסטבק ל-GA4 נכשל בשקט, ההתקנות מופיעות ב-GA4 ללא מקור ומישהו מוסיף "פתרון" בדמות אירוע ידני.
שימוש בשם שמור של Google
פוסטבק שממופה ל-session_start, first_open או in_app_purchase נדחה או מעוות את הדוחות המובנים. בוחרים שם מרשימת האירועים המומלצים או שם מותאם ייחודי.
השוואת התקנות בין שני הכלים כבדיקת תקינות
install ב-AppsFlyer ו-first_open ב-GA4 נספרים לפי מזהים שונים, בחלונות שונים ועם SKAN ב-iOS. פער של עשרות אחוזים הוא תוצאה שכיחה גם כשההטמעה מושלמת. הבדיקה הנכונה היא על אירוע אחד, לא על ההתקנות.
איך בודקים שזה עובד?
בודקים בשלוש שכבות, מהמכשיר אל הדוח. בשכבה הראשונה מתקינים גרסת בדיקה, עוברים את המסע כולו עם חשבון Sandbox של החנות ומוודאים ב-DebugView של GA4 שכל אירוע מהמילון מופיע פעם אחת עם הפרמטרים שלו. במקביל פותחים ב-AppsFlyer את ה-SDK integration test או את הנתונים הגולמיים של המכשיר ובודקים שאותם אירועים מופיעים גם שם, עם af_revenue רק במקום שהוחלט עליו.
בשכבה השנייה בודקים את החיבור. ב-AppsFlyer, בלוג הפוסטבקים של השותף GA4, מוודאים שפוסטבק ההתקנה יצא עם app_instance_id ולא נדחה. ב-GA4, יום לאחר מכן, פותחים את דוח Traffic acquisition של זרם האפליקציה ומחפשים את מקור המדיה שהגיע מ-AppsFlyer על ה-first_open של מכשיר הבדיקה. אם יש BigQuery, שאילתה על אירועי מכשיר הבדיקה מראה בבירור אם אירוע כלשהו הגיע משני מקורות.
בשכבה השלישית, אחרי שבוע של נתונים אמיתיים, משווים נתוני דמו כמו אלה: אם ב-GA4 יש 1,000 אירועי in_app_purchase ו-0 אירועי purchase, המסלול נקי. אם יש 1,000 ו-980, יש מיפוי כפול. בודקים גם שסך af_revenue ב-AppsFlyer בחודש קרוב להכנסה שהחנות מדווחת ולא כפול ממנה. הסימן שהעבודה הושלמה הוא שכל שאלה מהטבלה הראשונה מקבלת תשובה מכלי אחד. סימן נוסף הוא שאין אירוע שמופיע בשניהם מבלי שמישהו החליט שזה רצוי.
אם באפליקציה שלכם AppsFlyer ו-Firebase מראים מספרים שאי אפשר ליישב, או שאתם לפני השקה ורוצים מילון אירועים אחד לשני הכלים, אנחנו בונים את מסמך המדידה, מגדירים את האינטגרציה ובודקים אותה מקצה לקצה. פרטים בעמוד ניטור אפליקציות, בעמוד מדידה מתקדמת או דרך טופס הקשר.
עוד שכבה שלא נכנסת לאף אחד משני הכלים האלה היא יציבות. קריסה בשלב התשלום מוחקת את ההמרה שרק מדדתם. לכן לצד AppsFlyer ו-GA4 צריך גם ניטור קריסות עם ספים נכונים. מה מודדים ב-Firebase Crashlytics ואיך מחברים קריסות להמרות.
עוד מדריכים בנושא אנליטיקס לאפליקציות
מקורות
AppsFlyer Help Center: Google Analytics (GA4) integration, AppsFlyer Help Center: About ATT and SKAN, AppsFlyer Help Center: About ROI360 store revenue, Analytics Help: Automatically collected events, Analytics Help: How app key events are attributed
