京東金融客戶端使用者觸達方式的探索與實踐

語言: CN / TW / HK

一、關於使用者觸達

使用者觸達:可以簡單理解為通過某種方式將訊息傳遞給使用者的行為;觸達的特定訊息從功能上可分展示、引導落地兩層。使用者觸達作為一種產品運營方式,已經融入我們日常生產活動的方方面面。在移動網際網路的世界裡,我們的產品離不開觸達,使用者活動也離不開觸達。

 

二、為什麼做使用者觸達

以使用者使用角度來看,使用者在使用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為httphttps

2.配置一個數字資產連結的Json檔案,宣告你的網址和應用之間的關係;

對於在上述intent filter裡找到的每一個唯一的域名,Android系統會到對應的域名下查詢數字資產檔案,地址是:http://域名
/.well-known/assetlinks.json

只有當系統為AndroidManifest裡找到的每一個域名找到對應的數字資產檔案,系統才會把你的應用設定為特定連結的預設處理器。

數字資產示例:

package_name:在build.gradle裡定義的application ID

sha256_cert_fingerprints:應用簽名的SHA256指紋資訊,這個欄位支援多個指紋資訊,可以用來支援不同的應用版本,如開發版本和釋出版本然後將assetlinks釋出到http://域名
/.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 確認數字資產檔案是否被正確地定義和釋出:

http://digitalassetlinks.googleapis.com/v1/statements:list?

source.web.site=http://你的域名:可選的埠

&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:
http://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(AppEnvironment.getApplication().getApplicationContext())
                    .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、站內橫幅、小元件幾種觸達方式的探索實踐過程以及遇到的問題和解決方案。希望能給在探索使用者觸達實現方案的同學提供一些思路;為了讓使用者在使用我們的產品的時候能有更好的體驗,產品在運營過程中能高效的觸達使用者,京東科技技術團隊在持續打磨已有方案的同時將繼續探索和實踐更加智慧高效的觸達方案。