Apple がまもなく導入する App Tracking Transparency(ATT)ポリシーでは、他の企業のアプリやウェブサイトの一部の情報を広告目的で使う場合、その許可を得ることが必須となります。これには、すでにユーザーの同意を得ている場合も含まれます。iOS エコシステムのデベロッパーや広告主はまだ適応する方法を模索している状況なので、今日は Google がどのようにコミュニティの準備をサポートしているかについてお知らせします。
アプリを iOS 14 に対応させる
Apple が ATT を変更することにより、広告がどの程度コンバージョン(アプリのインストールや販売)を促進しているかを示す重要な指標の一部が見えなくなります。これは、広告主による広告インプレッションの価値評価や入札に影響します。そのため、Apple の ATT ポリシーが適用されると、アプリの発行元は、iOS での Google 広告の収益に重大な影響が発生する可能性があります。iOS の収益化率を向上するには、Google Mobile Ads SDK のバージョン 7.64 にアップグレードし、SKAdNetwork サポートなどの新機能を利用することをお勧めします。アプリの発行元が準備できることの詳細は、こちらをご覧ください。
iOS 14 での広告パフォーマンスの測定
Google は、iOS 14 で広告主がキャンペーンの結果を正確に測定できるように、業界と連携して、SKAdNetwork の改善に関するフィードバックを Apple に提供しています。改善が行われるまでの間は、最新バージョンの Google Analytics for Firebase にアップグレードし、SKAdNetwork サポートなどの新機能を利用することをお勧めします。また、すべての iOS のアプリ キャンペーンのパフォーマンスや成果を細かく監視し、必要に応じて目標を達成できるように予算や入札を調整することをお勧めします。アプリの広告主が準備できることの詳細は、こちらをご覧ください。また、一連のガイドは Learn with Google 教育シリーズに掲載されています。
広告主がウェブベースのコンバージョン目標に向けてディスプレイ、動画などのキャンペーンをしている場合、Apple の ATT ポリシーが適用される際に実績が変動する可能性があります。この期間には、推定コンバージョンを拡張してより多くの iOS 14 トラフィックに対応できるようにする予定です。
ATT への準拠の仕組み
Apple のポリシーが適用されると、現在広告目的で ATT に該当する(IDFA などの)情報を利用しているいくつかの Google 製 iOS アプリで、その情報を利用できなくなります。そのため、Apple のガイドに従い、これらのアプリには ATT プロンプトは表示しません。私たちは、App Store のすべての Google 製アプリについて、Apple のガイドを理解してそれに準拠する作業を懸命に進めています。新機能やバグの修正などで Google 製 iOS アプリがアップデートされると、アプリの掲載情報ページで App のプライバシーに関する詳細情報が新しくなるのを確認できます。
Google は、常にユーザーとプライバシーを最優先しています。透明性、選択肢、制御は、ユーザーに対する私たちの献身の根底であり、それは広告でも同様です。Google は、プライバシーと選択肢が確かに尊重され、広告によってサポートされる幅広いコンテンツにアクセスでき、活発でオープンなアプリのエコシステムをこれからも守り続けます。集計ソリューションやオンデバイス ソリューションなどのプライバシー保護技術に注力し続けているのはそのためです。現在、エコシステム パートナーとともにウェブで開発しているプライバシー サンドボックスもその 1 つです。
この記事は プロダクト マネージャー 、Jumana Al Hashal による The Firebase Blog の記事 "Making Dynamic Links Easier" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。
Firebase Dynamic Links は便利なリンクシステムです。1 つだけのリンクで、インストール済みの iOS や Android アプリを開き、ディープリンクを使用し、ユーザーが探しているコンテンツを直接にアプリ内で表示することができます。アプリがインストールされていない場合にも、同じリンクで App Store や Google Play のアプリのページからアプリ内のコンテンツまで案内することができます。
let authOptions : UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(options: authOptions)
{ (granted, error) in
if (error != nil) {
print("I received the following error: \(error)")
} else if (granted) {
print ("Authorization was granted!")
} else {
print ("Authorization was not granted. :(")
}
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions
// ...
printFCMToken() // This will be nil the first time, but it will give you a value on most subsequent runs
NotificationCenter.default.addObserver(self,
selector: #selector(tokenRefreshNotification),
name: NSNotification.Name.firInstanceIDTokenRefresh,
object: nil)
application.registerForRemoteNotifications()
//...
}
func printFCMToken() {
if let token = FIRInstanceID.instanceID().token() {
print("Your FCM token is \(token)")
} else {
print("You don't yet have an FCM token.")
}
}
func tokenRefreshNotification(_ notification: NSNotification?) {
if let updatedToken = FIRInstanceID.instanceID().token() {
printFCMToken()
// Do other work here like sending the FCM token to your server
} else {
print("We don't have an FCM token yet")
}
}
SELECT
user_dim.geo_info.country as country,
EXACT_COUNT_DISTINCT( user_dim.app_info.app_instance_id ) as users
FROM
[firebase-analytics-sample-data:android_dataset.app_events_20160601],
[firebase-analytics-sample-data:ios_dataset.app_events_20160601]
GROUP BY
country
ORDER BY
users DESC
SELECT
user_dim.user_properties.value.value.string_value as language_code,
EXACT_COUNT_DISTINCT(user_dim.app_info.app_instance_id) as users,
FROM
[firebase-analytics-sample-data:android_dataset.app_events_20160601],
[firebase-analytics-sample-data:ios_dataset.app_events_20160601]
WHERE
user_dim.user_properties.key = "language"
GROUP BY
language_code
ORDER BY
users DESC
SELECT
event_dim.name,
COUNT(event_dim.name) as event_count
FROM
[firebase-analytics-sample-data:android_dataset.app_events_20160601]
GROUP BY
event_dim.name
ORDER BY
event_count DESC
SELECT
event_dim.params.value.int_value as virtual_currency_amt,
COUNT(*) as num_times_spent
FROM
[firebase-analytics-sample-data:android_dataset.app_events_20160601]
WHERE
event_dim.name = "spend_virtual_currency"
AND
event_dim.params.key = "value"
GROUP BY
1
ORDER BY
num_times_spent DESC
SELECT
user_dim.geo_info.city,
COUNT(user_dim.geo_info.city) as city_count
FROM
TABLE_DATE_RANGE([firebase-analytics-sample-data:android_dataset.app_events_], DATE_ADD('2016-06-07', -7, 'DAY'), CURRENT_TIMESTAMP()),
TABLE_DATE_RANGE([firebase-analytics-sample-data:ios_dataset.app_events_], DATE_ADD('2016-06-07', -7, 'DAY'), CURRENT_TIMESTAMP())
GROUP BY
user_dim.geo_info.city
ORDER BY
city_count DESC
SELECT
user_dim.app_info.app_platform as appPlatform,
user_dim.device_info.device_category as deviceType,
COUNT(user_dim.device_info.device_category) AS device_type_count FROM
TABLE_DATE_RANGE([firebase-analytics-sample-data:android_dataset.app_events_], DATE_ADD('2016-06-07', -7, 'DAY'), CURRENT_TIMESTAMP()),
TABLE_DATE_RANGE([firebase-analytics-sample-data:ios_dataset.app_events_], DATE_ADD('2016-06-07', -7, 'DAY'), CURRENT_TIMESTAMP())
GROUP BY
1,2
ORDER BY
device_type_count DESC
SELECT
STRFTIME_UTC_USEC(eventTime,"%Y%m%d") as date,
appPlatform,
eventName,
COUNT(*) totalEvents,
EXACT_COUNT_DISTINCT(IF(userId IS NOT NULL, userId, fullVisitorid)) as users
FROM (
SELECT
fullVisitorid,
openTimestamp,
FORMAT_UTC_USEC(openTimestamp) firstOpenedTime,
userIdSet,
MAX(userIdSet) OVER(PARTITION BY fullVisitorid) userId,
appPlatform,
eventTimestamp,
FORMAT_UTC_USEC(eventTimestamp) as eventTime,
eventName
FROM FLATTEN(
(
SELECT
user_dim.app_info.app_instance_id as fullVisitorid,
user_dim.first_open_timestamp_micros as openTimestamp,
user_dim.user_properties.value.value.string_value,
IF(user_dim.user_properties.key = 'user_id',user_dim.user_properties.value.value.string_value, null) as userIdSet,
user_dim.app_info.app_platform as appPlatform,
event_dim.timestamp_micros as eventTimestamp,
event_dim.name AS eventName,
event_dim.params.key,
event_dim.params.value.string_value
FROM
TABLE_DATE_RANGE([firebase-analytics-sample-data:android_dataset.app_events_], DATE_ADD('2016-06-07', -7, 'DAY'), CURRENT_TIMESTAMP()),
TABLE_DATE_RANGE([firebase-analytics-sample-data:ios_dataset.app_events_], DATE_ADD('2016-06-07', -7, 'DAY'), CURRENT_TIMESTAMP())
), user_dim.user_properties)
)
GROUP BY
date, appPlatform, eventName
Google Analytics に同じアプリのデータがあれば、BigQuery に Google Analytics データをエクスポートし、Firebase Analytics BigQuery 表と JOIN することもできます。
アナリティクス データの視覚化
生データの BigQuery エクスポートによって、モバイルアプリのデータを使った洞察を行えるようになりました。次は、Google Data Studio を使ってデータを視覚化してみましょう。Data Studio は、BigQuery 表から直接読み出すことができます。さらに、前述のようなカスタムクエリを渡すことも可能です。Data Studio は、データ構造に応じて、時系列グラフ、棒グラフ、円グラフ、地図など、さまざまなタイプのグラフを生成できます。
最初の視覚化の例として、各プラットフォームでユーザーがアプリにアクセスする際に使っている端末のタイプを比較する棒グラフを作成してみましょう。モバイルとタブレットを比較する前述のクエリを直接 Data Studio に貼り付けると、次のグラフを生成できます。
ステートは、ただの変化するデータです。このデータがステートと呼ばれるのは、アプリケーションの「ステート」(状態)を示しているからです。このデータが変化すると、アプリケーションの表示が変化する可能性が高いため、異なる「ステート」になると表現できます。一般的に、ステートは ToDo リストの項目や、有効 / 無効ボタンのようなものです。