用戶觸達:可以簡單理解為通過某種方式將消息傳遞給用戶的行為;觸達的特定消息從功能上可分展示、引導落地兩層。用戶觸達作為一種產品運營方式,已經融入我們日常生產活動的方方面面。在移動互聯網的世界里,我們的產品離不開觸達,用戶活動也離不開觸達。 ...
一、關於用戶觸達
用戶觸達:可以簡單理解為通過某種方式將消息傳遞給用戶的行為;觸達的特定消息從功能上可分展示、引導落地兩層。用戶觸達作為一種產品運營方式,已經融入我們日常生產活動的方方面面。在移動互聯網的世界里,我們的產品離不開觸達,用戶活動也離不開觸達。
二、為什麼做用戶觸達
以用戶使用角度來看,用戶在使用App的過程中會有一些與用戶相關的系統類的通知,比如交易物流、客服消息、賬單信息,借還款提醒,實時資訊等消息需要及時的給用戶提醒;
以APP運營活動看,App在日常運營過程中,根據當前的目標,結合活動向用戶定向發送相關營銷類信息,比如單品的活動信息或一些品類促銷優惠等,引導用戶快速進入活動頁面;
因此觸達在拉新、促活、留存、變現、自傳播等運營活動中扮演者重要角色。這篇文章從app 研發視角介紹下用戶觸達方面的一些實踐。
三、觸達用戶的方式實踐
從APP的存活狀態區分,實現觸達有兩種方式,一種是:APP非活躍狀態時的站外觸達,主要包含:簡訊、Push、桌面小組件等
另一種是:APP活躍狀態時的站內觸達,主要包含站內彈窗、頁面固定運營位,feed流推薦位等。
下麵介紹下一下我們實現的幾種觸達方式及遇到的一些問題。
觸達方式一:簡訊
簡訊起初應用最廣泛的場景是作為我們交流溝通的一種方式,隨著時代的發展微信、QQ等即時通訊類的app逐漸代替了簡訊作為人與人溝通工具,但是由於簡訊能夠及時穩定的將消息同步給用戶的特點,它仍是我們現在使用比較廣泛的消息觸達方式。常見的應用場景如:驗證碼通知、還款提醒、賬戶變動、營銷活動通知等。我們知道作為一種觸達方式,它的使命不僅是將消息通知到用戶,對於特定的消息還要能便捷的引導用戶跳轉到APP內的相應的落地頁。
簡訊的消息觸達能力是毋庸置疑的,雖然簡訊文本中直接放入的鏈接我們也可以打開,但是確存在一些局限性,這種方式僅支持打開web頁面,無法跳轉到APP原生頁面,另外點擊鏈接會先彈窗,由用戶選擇打開鏈接的app,這種體驗相比直接打開APP指定頁面來說大打折扣。因此,如何通過簡訊直接到達APP內
相應的落地頁就是我們需要解決的問題。google提供了一種能使Android系統直接通過網站地址打開應用程式對應內容頁面,而不需要用戶選擇使用哪個應用來處理網站地址的方式,即Android App Links;其工作流程如下:
要添加Android App Links到應用中,需要在應用里定義通過Http(s)地址打開應用的intent filter,並驗證你確實擁有該應用和該網站。
如果系統成功驗證到你擁有該網站,那麼系統會直接把URL對應的intent路由到你的應用。
1.在AndroidManifest里配置用於系統進行驗證的IntentFilter:
當android:autoVerify="true"出現在你任意一個intent filter里,在Android 6.0及以上的系統上安裝應用的時候,會觸發系統對APP里和URL有關的每一個功能變數名稱的驗證。驗證過程設計以下步驟:
系統會檢查所有包含以下特征的intent filter:Action為
android.intent.action.VIEW、Category為
android.intent.category.BROWSABLE和
android.intent.category.DEFAULT、Data scheme為http或https
2.配置一個數字資產鏈接的Json文件,聲明你的網址和應用之間的關係;
對於在上述intent filter里找到的每一個唯一的功能變數名稱,Android系統會到對應的功能變數名稱下查找數字資產文件,地址是:https://功能變數名稱
/.well-known/assetlinks.json
只有當系統為AndroidManifest里找到的每一個功能變數名稱找到對應的數字資產文件,系統才會把你的應用設置為特定鏈接的預設處理器。
數字資產示例:
package_name:在build.gradle里定義的application ID
sha256_cert_fingerprints:應用簽名的SHA256指紋信息,這個欄位支持多個指紋信息,可以用來支持不同的應用版本,如開發版本和發佈版本然後將assetlinks發佈到https://功能變數名稱
/.well-known/assetlinks.json
[ { "relation": [ "delegate_permission/common.handle_all_urls" ], "target": { "namespace": "android_app", "package_name": "xxx.xxx.xx", "sha256_cert_fingerprints": [ "xx:xx...." ] } } ]
3.跳轉落地頁
在配置了上述intent filter的Activity中解析url,並執行跳轉落地頁等操作
4.問題及排查方法
如果配置後點擊簡訊的鏈接無法正常跳轉,可以逐個排查相關配置是否正確
4.1 確認數字資產文件是否被正確地定義和發佈:
https://digitalassetlinks.googleapis.com/v1/statements:list?
source.web.site=https://你的功能變數名稱:可選的埠
&relation=delegate_permission/common.handle_all_urls
4.2 確認應用是否設置了正確鏈接處理方式:
adb shell am start -a android.intent.action.VIEW \
-c android.intent.category.BROWSABLE \
-d "http://你的功能變數名稱:可選的埠"
4.3 檢查鏈接策略
這一步需要在應用安裝後,等待一段時間10s後再執行,因為應用安裝後系統會請求解析配置表
執行:adb shell dumpsys package domain-preferred-apps 或 adb shell dumpsys package d
該命令返回了設備上每一個應用配置的列表,這個列表標明應用和網站之間的關聯
App linkages for user 0:
Package: com.android.demo 代表應用包名
Domains: play.google.com market.android.com 網站功能變數名稱,多個網站之間用空格分隔
Status: always : xxxx 表示應用在Manifest文件里的配置了 android:autoVerify="true" 狀態為 always;後面的xxxx和驗證是否成功無關,和系統中應用的配置記錄有關;
4.4 解決機型相容性適配問題
在實踐過程中還發現各廠商的不同型號的設備上存在無法跳轉到落地頁的情況,經分析該機型上應用安裝後系統請求解析配置表assetlinks過程失敗,此時會使用系統預設瀏覽器打開落地頁,落地頁是app原生頁面的無法跳轉到落地頁,對於需要登錄的web頁面,如果未在登錄中心註冊的也會跳轉失敗,並會重定向到m.jd.com 。
解決方案:有問題的機型,使用統一下載頁中轉,下載頁執行喚起APP,APP內處理跳轉落地頁邏輯。
觸達方式二:Push推送
1.客戶端推送方案
Google 為 Android 提供了 FCM 推送,但是因為網路服務等一些原因其可用性不佳;目前國內各廠商rom也都提供了免費的push推送接入能力,同簡訊比push由於其免費性極大地節約了觸達成本。
同時國內也有一些三方推送服務供應商,我們結合京東金融自身業務特點,為了保障數據的安全性以及推送消息的服務質量,最終採取整合華為,小米,OPPO、ViVO、魅族各廠商推送能力與自建通道相結合的方案。
其中廠商推送特點:token有效期內,用戶殺死app 可以接收到push消息;自建通道特點:app啟動後建立連接,接收push消息,殺死APP後收不到push消息,主要用於使用未適配的廠商設備如三星、努比亞等用戶接收push消息。
各廠商在push方案的實現上大體相同(廠商push接入流程,下圖以MiPush為例),在使用廠商推送的過程中我們也遇到了很多問題,因此瞭解了各廠商的特性是制定出良好的觸達策略前提。
2.廠商推送遇到的問題
2.1 push通知消息是否可以個性化展示
通常情況下通知欄消息展示效果主要內容包括消息標題、摘要、應用圖標和時間。客戶端可以自行定義具體展示內容。
不同廠商如華為、OPPO、vivo、小米、魅族等通知欄樣式存在一些不同綜合對比如下表:
在通知展示的樣式上,綜合對比來看華為支持inBox的樣式,OPPO小米支持大圖樣式,可以通過這些特點定製出更有特色的通知展示形式來突出通知主題。
華為inBox樣式:Inbox樣式將每行內容都當作獨立的單行文本去展示。文本內容最多可展示5行,每行內容展示不了時後邊自動添加“...”
OPPO小米支持大圖樣式:這種通知可以將更有吸引力的圖片展示給用戶
2.2 App有很多業務推送通知,用戶是否可以指定接收分類消息
隨著APP的業務越來越複雜,應用的通知越來越多,給用戶造成明顯打擾;
用戶只能全局屏蔽這個應用的全部通知,不能屏蔽部分,然後留下對自己有用的。
為瞭解決這個問題,Android 8.0開始支持開發者給自己的通知分成若幹類,然後允許用戶單獨屏蔽這個類別的通知。
需要進行Channel 分類,添加新Channel(以MiPush為例):
ChannelHelper channelHelper = new ChannelHelper(APP_SECRET); ChannelInfo channelInfo = new ChannelInfo.Builder() .channelId("id") //必填,通知類別的ID,長度不超過 200 字元 .channelName("name") //必填,通知類別的名稱,長度不超過40字元 .channelDesc("desc") //可選,通知類別的描述,長度不超過300字元 .notifyType(0) //必填,通知的效果類型,僅支持0,即振動、提示音、led燈三種效果都無 .soundUrl("sound_url") //可選,通知的自定義鈴聲uri,格式介紹請參見 “4.1 自定義鈴聲” .build(); Result result = channelHelper.addNewChannel(channelInfo, 1)
不同的channel在系統設置頁通知設置中展示如下:
通過細分push通知的類別,增加通道數量可提高push消息在通知欄里的留存率;
同時用戶可有更多選擇,設置自己比較關註的類型消息,避免過多打擾,以提升用戶體驗。
2.3 如何指定推送方式或人群
各廠商推送方式支持方式如下:
2.3.1 基於ReglD的推送
RegID為是推送SDK為每個設備上的每個app註冊推送服務時生成的唯一標示。
當開發者需要給一個或多個具體的設備推送消息時,可以使用基於 RegID的推送,將個性化的信息推送給指定的設備。這種方式適用於需要為每個用戶訂製個性化推送的場景。
2.3.2 基於Alias的推送
alias是推送提供的一種個性化設定, 開發者可以將用戶在應用內的賬號或其它用戶唯一標識設定為用戶設備 RegID 的別名,在推送中可以直接基於別名進行推送。
別名不僅方便開發者將推送與自有的賬號系統進行關聯,同時也避免了因需要保存設備 RegID 與自有帳號的對應關係而額外帶來的開發和存儲成本。
2.3.3基於標簽的推送
對應用下已訂閱push的設置了標簽的用戶進行推送。在推送消息時,開發者可以結合每條消息的內容和目標用戶人群,選擇所對應的標簽,完成請求後,push推送服務會向所有
打上這一標簽的用戶發送該消息,從而滿足定向推送的需求。並且提供標簽管理功能。
2.3.4 小米通道userAccount :最多可對應20台設備,單賬號可登陸多台設備,給一個 userAccount 推送可同時有20台設備收到消息。
總結:將特定的推送消息通過特定的方式發送給比如不同的客戶端版本、 不同地域、男女等的用戶群體,或者通過給不同的用戶群體打不同的標簽的方式實現特性消息的推送,以達到更精細推送的目的。
2.4 OPPO、ViVO觸達成功率低,如何提升
觸達數據接入數據看板後,經對比各廠商觸達成功率發現OPPO、ViVO的觸達率基本在83%~86%而小米華為通道觸達成功率基本在94%~98%因此提升OPPO、VIVO通達的觸達成功率是我們面臨的又一問題
OPPO:經排查發現影響OPPO觸達率的主要因素為通知開關的狀態:APP 僅在通知開關開啟的情況下才能收到廠商的Push消息而OPPO、一加通知開關在用戶安裝後預設關閉,因此收不到Push消息。
解決辦法:前期主要是制定引導策略,在合適的時機檢測通知開關狀態,引導用戶主動去設置頁開啟,後來經調研發現OPPO的 ColorOS 系統提供了一鍵開啟通知開關的能力,後期使用引導一鍵開啟方案,將OPPO通道的觸達率提升到了94%左右;
VIVO:與OPPO不同,VIVO設備安裝應用後通知開關是開啟的,我們根據數倉提供的數據與廠商反饋的錯誤碼分析,導致VIVO觸達偏低主要因素為消息未進行分類而被限額。
vivo通道消息類型分為兩類——按消息類型是否與用戶強相關將消息分為“運營消息”和“系統消息”,未接消息分類功能將導致所有消息預設為運營消息而受到頻控限制,從而導致重要消息可能無法觸達。
vivo用戶單應用每日運營消息接收條數上限5條,系統消息無限制。vivo用戶單應用接收條數限制以“到達量”是否超過5條為準,在發送時校驗單用戶是否到達5條,超限則計入管控量。
除VIVO外,華為、OPPO、小米對通知消息的數量 都有一定的限制,對於存在限額的廠商通道,將點擊率高的個性化推送策略儘量安排在上午推送,可以保證優質推送內容的到達率;通過提高消息推送的額度,提高push消息的觸達率。
2.5 如何增強未讀消息提醒
可以在App桌面角標顯示未讀消息數,廠商lunch app 和 push sdk對此提供了相應的能力支持,用於增強提醒,各廠商的實現細節上有差異:
華為:角標未讀數由服務端下發的push消息控制,開放了api供第三方應用設置角標未讀數,移除通知欄消息角標數量不會變化。
小米:角標未讀數等於廠商push通道(系統通知欄)收到的該app的未讀通知數,開放api供第三方應用設置角標未讀數。移除系統通知欄消息,角標數量相應減少。
oppo:支持紅點,數字角標,角標未讀數等於廠商push通道(系統通知欄)收到的該app的未讀通知數。
vivo:桌面角標未讀數開關預設關閉,需要用戶手動開啟才能使用,提供設置角標未讀數的能力。
角標適配的問題及解決辦法:
2.5.1 在小米系統上能展示通知數,但無法更新站內信數量。
解決方案:站內信和push打通,進入app時同步更新未讀數。
2.5.2 在華為系統上無法顯示Push數量,站內信數顯示正常。
解決方案:華為推送服務提供了在服務端設置桌面角標API介面,第三方app可以在消息中封裝角標參數。
2.5.3 vivo手機上不支持顯示角標未讀數。
解決方案:更新SDK版本,接入角標能力
2.5.4 在oppo角標展示僅站內信數量。
push功能在開通時可以申請圓點角標或數字角標、無角標三種形式,用戶可以在通知設置中自主選擇。
oppo push支持的系統版本,目前支持 ColorOS3.1及以上的系統的OPPO的機型,一加5/5t及以上機型,realme所有機型(Android 8.0 以後的設備)。
2.5.5 其他:魅族手機未開放桌面角標設置。
觸達方式三:站內橫幅
1.站內橫幅方案介紹
已有的觸達方式對用戶實時行為產生的場景覆蓋不夠,而且這類場景較離線場景相比實時性更高,對用戶來說相對更重要。針對這個情況,我們增加了對實時場景覆蓋。
目的是將用戶行為抽象成關係模型,當關係一側的用戶行為發生變更後觸發對另一側的觸達,這種情況實時性更強而且和用戶強相關,觸達的消息點擊和轉化都比較高,也有利於增強用戶粘性。
數據服務層:各業務模塊負責採集用戶行為數據,由molo側將用戶行為抽象關係模型,用戶進入指定場景,觸發對應場景觸達策略,再經統一頻控量控進行核驗
傳輸層:基於MQTT協議的長鏈接實現的鷹眼自建通道,將通過核驗的觸達信號傳遞給下一流程
APP基礎能力層:為觸達消息傳輸,流程監控提供基礎能力
數據解析層:將傳遞過來的觸達消息體解析,合法性校驗,監控異常數據
視圖控制層:進行觸達消息模板視圖創建,彈出方式識別,通過ViewCore給觸達消息視圖註入生命周期,出入場動畫,聲音震動提醒、展示動效等各種定製化屬性
2.京東金融App站內橫欄應用場景
站內橫欄功能上線後,為一批業務提供了有效的觸達策略
3.遇到的問題及解決思路
3.1 如何讓橫欄實現在App站內全局
全局彈窗這個實現起來相對容易,主要依賴註冊的頁面生命周期監聽,利用WindowManager在離開頁面時移除view ,在進入新頁面重新添加;
3.2 指定頁面顯示或指定頁面不顯示問題
指定頁面的前提是能區分是哪個頁面,分兩種情況:
Web頁面,首先獲取運營在鷹眼平臺配置的指定的Web鏈接,再通過APP的web容器獲取當前正在加的web頁面的鏈接地址,兩個地址進行匹配,需要註意本地取到的url里參數存在比運營配置多的情況,因此匹配時我們認為只要本地取到的參數包含配置的地址中的各參數即是匹配成功;
原生頁面,方式一,路由地址匹配:我們首先取原生頁面的路由信息,本地有路由信息根據路由地址去匹配,若原生頁面無路由地址,需要進行適配
方式二,popClass匹配:需要將原生頁面的類路徑錄入到後臺頁面配置表進行維護,匹配時根據頁面的類路徑進行匹配
3.3 如何避免多個橫欄消息時丟失問題
同時支持多個橫欄,這裡需要註意的是橫欄信息同步問題,我們在創建橫欄的時候給橫欄創建了一個屬性信息對象,每個橫欄屬性信息都有唯一的key,將橫欄屬性緩存起來,並給緩存設置最大閾值,達到閾值時最後一個橫欄消失清除緩存信息
總結:站內橫欄觸達方案是我們在智能化觸達方式中的一項探索,功能上線後,為白條,保險,財富,基金,分期等業務提供了一種更智能化的運營方式,觸達消息觸達成功率98%,點擊率達到12%~16%,助力相關業務提升40%以上
觸達方式四:桌面小組件
AppWidget 又稱小部件、小插件或微件。它是顯示在Launcher上,能在Logo以外提供更多信息的一種特別的設計;它方便用戶免於打開App即可直接查看信息和進行簡單的交互。
- Android 初期已經提供這種能力,但應用比較少,常見的應用如:時鐘、天氣、日曆等;
- iOS 10引入小組件,直到iOS 14的全面支持,可能是受此影響,Android 12 改進了widgetAPI,提升了用戶及開發者體驗
1.創建AppWidget
總的來說分以下幾個部分:
1.1 定義AppWidgetProvider
創建一個AppWidgetProvider子類,並創建對應的AppWidgetProviderInfo 配置文件
example_appwidget_info.xml,併在manifest聲明
1.2 設置appWidget 的基本屬性
AppWidgetProviderInfo定義了widget的基本特性,如應用微件的最小佈局尺寸、應用微件的初始佈局資源、應用微件的更新頻率,以及(可選)在應用微件創建時啟動的配置 Activity。您可以使用單個 <appwidget-provider> 元素在 XML 資源中定義 AppWidgetProviderInfo 對象,並將其保存在項目的 res/xml/ 文件夾中
1.3 繪製widget的佈局
AppWidget可以支持的佈局如下(由於其底層是基於RemoteViews實現,支持的視圖較少):
- FrameLayout、LinearLayout、RelativeLayout、GridLayout
支持使用的View如下(不支持自定義View):
- AnalogClock、Button、Chronometer、ImageButton、ImageView、ProgressBar、TextView、ViewFlipper、ListView、GridView、StackView、AdapterViewFlipper
1.4 配置Configuration Activity
當應用widget使用配置 Activity 時,由該 Activity 負責在配置完成後對 app 的widget進行初始化
1.4.1 獲取widget id
1.4.2 執行應用微件配置
1.4.3 配置完成後,通過調用 getInstance(Context) 來獲取 AppWidgetManager 的實例
1.4.4 通過調用 updateAppWidget(int, RemoteViews) 來使用 RemoteViews 佈局更新應用微件
1.4.5.最後,創建返回 Intent,為其設置 Activity 結果,然後結束該 Activity
1.4.6 設置預覽圖片
在選擇創建appWidget時,展示給用戶的描繪應用微件是什麼樣子的一張圖片,未配置時預設展示APP logo
1.4.7 配置Service
請求集合中的特定項目時,RemoteViewsFactory 會為集合創建相應項目並將其作為 RemoteViews 對象返回。要在appWidget中添加集合視圖,您必須實現 RemoteViewsService 和 RemoteViewsFactory。
詳細參見官方demo:
https://android.googlesource.com/platform/development/+/master/samples/StackWidget/src/com/example/android/stackwidget/StackWidgetService.java
1.4.8 設置點擊事件
通常使用 setOnClickPendingIntent() 來設置對象的點擊行為 - 例如,讓按鈕啟動 Activity。但是,不允許對各個集合項目中的子視圖使用此方法。如果要向集合中的各個項目添加點擊行為,應改用 setOnClickFillInIntent()。這需要為集合視圖設置待定 Intent 模板,然後通過 RemoteViewsFactory 在集合中的每個項目上設置填充 Intent。
2.常見App的實現
金融APP的實現:
3.小組件實踐中的問題
3.1 如何裁剪圖片圓角
一般在開發過程中使用Glide對圖片進行裁剪,這裡需要註意小組件里使用Glide與平常略有不同,因為拿不到對應的View視圖,AppWidgetTarget更適用於小組件載入圖片場景,配合MultiTransformation 可簡便的實現圖片圓角的剪裁
AppWidgetTarget appWidgetTarget = new AppWidgetTarget(context, ivViewId, views, mAppWidgetIds);
RequestOptions option = new RequestOptions()
.transform(new MultiTransformation<>(
new CenterCrop(),
new RoundedCorners(ToolUnit.dipToPx(mContext, connerDp))));
GlideApp.with(context)
.asBitmap()
.load(bgUrl)
.apply(option)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(appWidgetTarget);
3.2 如何實現自定義字體
小組件本身是不支持自定義view的,若要實現支持自定義字體,可以通過Canvas draw text 方式 給 text 設置字體樣式,粗細、顏色 、背景等屬性
3.3 處理點擊響應延遲問題
通過廣播形式PendingIntent.getBroadcast 處理點擊事件,在部分機型上存在延時,最長約7s;可以使用setOnClickPendingIntent方式代替,需要在app的跳轉中心處理對應的事件,如跳轉落地頁、埋點等
3.4 如何制定更新策略
系統為了避免小組件過多的占用資源,預設拒絕頻繁更新,設置了最短更新時間為30分鐘;這種預設的刷新方式不太適合交互類型的小組件,存在用戶操作完以後頁面狀態不同步的問題,那這個問題如何解決呢?首先根據業務場景需要我們也可以把刷新分為兩類:
實時性有一定要求的業務場景:比如新聞資訊類的
通過創建Service開啟定時任務的方式,制定更新的時間間隔,比如5分鐘執行一次更新任務;
用戶交互類型的業務場景:比如簽到,收積分、能量等;此類場景不要求頻繁刷新數據,但需要配置合理的自動刷新時間,同時在用戶操作後需要刷新頁面;可以在App啟動時註冊APP內頁面生命周期監聽
ActivityLifecycleCallbacks,實現判斷APP前後臺監聽能力,監聽應用進入後臺時發送刷新小組件的廣播,觸發小組件的刷新;或者封裝統一方法,提供給業務主動觸發刷新對應的小組件的介面
小結
本文主要分享了京東金融客戶端技術團隊對簡訊、push、站內橫幅、小組件幾種觸達方式的探索實踐過程以及遇到的問題和解決方案。希望能給在探索用戶觸達實現方案的同學提供一些思路;為了讓用戶在使用我們的產品的時候能有更好的體驗,產品在運營過程中能高效的觸達用戶,京東科技技術團隊在持續打磨已有方案的同時將繼續探索和實踐更加智能高效的觸達方案。