This article introduces the data analysis plugin and customization method for miniapp
I. Overview of Plugin Framework and QuickTracking Analysis Plugin

1. Frontend
The miniapp needs to integrate "MiniApp PageEvent Report JS-library" to obtain "MiniApp Page Lifecycle Events" and send them to LifeCycleService via jsapi.
Note: This feature only supports WindVane miniapp container.
1.1. How to Integrate As shown below, in the miniapp's HTML file, include the following script tag https://g.alicdn.com/code/npm/@alife/windvane-page-lifecycle-hooks/0.1.0/index.js
Note: The order of inclusion is important; this script must be included after windvane.js.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, maximum-scale=1.0,viewport-fit=cover" />
<title>EMAS-WindVane JSBridge Demo</title>
<link rel="stylesheet" href="static/css/main.css" />
</head>
<body>
<div id="app"></div>
<!-- <script src="//g.alicdn.com/code/lib/react/18.2.0/umd/react.development.js"></script> -->
<!-- <script src="//g.alicdn.com/code/lib/react-dom/18.2.0/umd/react-dom.development.js"></script> -->
<!-- <script src="https://as.alipayobjects.com/g/component/fastclick/1.0.6/fastclick.js"></script> -->
<script src="https://g.alicdn.com/mtb/lib-windvane/3.0.0/windvane.js"></script>
<script src="https://g.alicdn.com/code/npm/@alife/windvane-page-lifecycle-hooks/0.1.0/index.js"></script>
<script src="static/js/bundle.js"></script>
</body>
</html>
1.2. Synchronize MiniApp Lifecycle
The lifecycle of the miniapp is as follows:
onPageStart: Triggered when the miniapp initialization is complete (triggered only once globally).
onPageShow: Triggered when the miniapp opens a page or comes to the foreground from the background.
onPageHide: Triggered when the miniapp leaves a page or goes to the background from the foreground.
onPageEnd: Triggered when the miniapp is closed.
The reported page parameters for the miniapp are as follows:
url: The current page URL, e.g., ,
https://g.alicdn.com/superapp-fe-templates/JSAPITest/1.0.1/index.html#/fullUrl: The current page URL, e.g., ,
https://g.alicdn.com/superapp-fe-templates/JSAPITest/1.0.1/index.html?spm=defwork.home.0.0.3f085c4bPdhs2c#/title: The current page title.
userAgent: The
navigator.userAgentof the current device, e.g.,"Mozilla/5.0 (Linux; Android 11; IN2010 Build/RP1A.201005.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/132.0.6834.163 Mobile Safari/537.36 TTID/600000@DemoApp_Android_1.0.0 WindVane/8.5.0"viewportHeight: The current viewport height, e.g.
744viewportWidth: The current viewport width, e.g.
384referrer: The source address of the currently requested page, e.g., ,
https://1511899753493821546496.app.mini.windvane.suite.emas.alibaba.com/user_id: userId, the userId parameter in the EMASUserInfoService(iOS),IUserInfoService(Android ) registered by container initialization.
mini_app_id: the appId of the opened miniapp.
mini_app_version: the version of the opened miniapp.
mini_app_type: the type of the opened miniapp, such as windvane or uniapp.
app_code: the appCode passed in when the container is initialized.
timestamp: page triggers current timestamp
1.2.1. Open the MiniApp

As shown in the diagram, the JSAPI will be called, and WVMiniPageEvent will report onPageStart and onPageShow, along with the page parameters shown in the diagram.
1.2.2. Page Navigation

As shown in the diagram, the JSAPI will be called, and WVMiniPageEvent will report onPageHide for the current page and onPageShow for the target page, along with the page parameters shown in the diagram.
1.2.3. Foreground to Background

As shown in the diagram, the JSAPI will be called, and WVMiniPageEvent will report onPageHide for the current page, along with the page parameters shown in the diagram.
1.2.4. Background to Foreground

As shown in the diagram, the JSAPI will be called, and WVMiniPageEvent will report onPageShow for the current page, along with the page parameters shown in the diagram.
1.2.5. Close the MiniApp

As shown in the diagram, the JSAPI will be called, and WVMiniPageEvent will report onPageHide and onPageEnd, along with the page parameters shown in the diagram.
2. Client: Android & iOS
2.1 MiniApp Event: Listens to mini program lifecycle events, including:
MiniApp Life Cycle Event | Android Activity | iOS ViewController |
start | onCreate | viewDidLoad |
show | onResume | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil]; |
hide | onPause | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil]; |
close | onDestory | viewWillDisappear (if (self.isMovingFromParentViewController|| self.navigationController.isBeingDismissed)) |
2.2 Listens to mini program page lifecycle events (only support WindVane)
2.3 A plugin framework used for plugin management:
Used to register plugins.
Used to retrieve specific plugins.
2.4 LifeCycleService
Used to receive miniapp page lifecycle events sent by the 'MiniApp PageEvent Report JS-library' via jsapi (MiniAppPageEvent jsapi).
Used to listen to miniapp lifecycle (MiniApp Event) events.
Sends miniapp page lifecycle events and miniapp lifecycle events to the reporting plugin via observer objects (Observer/Callback).
Currently, the lifecycle events monitored by LifeCycleService are as follows.
Event Type | Mini App Page Event | Mini App Event |
start | YES | YES |
show | YES | YES |
hide | YES | YES |
end/close | YES (only for Android) | YES |
II. Custom Plugin Development
1. Import dependency packages.
implementation com.aliyun.emas.suite.foundation:mini-app-plugin-base:1.0.0pod 'MiniAppPluginBase'2. Plugin development.
import com.alibaba.emas.android.windvane.mini.app.pluginsdk.plugin.BasePlugin;
public class CustomPlugin extends BasePlugin {
public CustomPlugin(Context context, ...) {
super(context);
...
}
@Override
public void start() {
...
}
...
}#import <EMASMiniAppService/EMASBasePlugin.h>
@interface EMASCustomPlugin : EMASBasePlugin
@property(nonatomic, strong) EMASPluginContext *plugContext;
@implementation EMASCustomPlugin
- (void)setPluginContext:(EMASPluginContext *)pluginContext {
self.plugContext = pluginContext;
}
- (void)start {
[super start];
// register Observer Object
}
import UIKit
import EMASMiniAppService
@objc class EMASCustomPlugin: EMASBasePlugin, EMASIMiniAppEventObserver, EMASIMiniAppPageEventObserver {
var plugContext:EMASPluginContext?
//Note: need to call the Swift setPluginContext method, remember to add @objc
@objc func setPluginContext(_ pluginContext: EMASPluginContext) {
self.plugContext = pluginContext
}
override func start() {
super.start()
///register Observer Object
}
}3. Plugin registration.
CustomPlugin customPlugin = new CustomPlugin(context, ...);
miniAppService.registerPlugin("PluginName", customPlugin);EMASCustomPlugin *plugin = [[EMASCustomPlugin alloc] init];
[miniAppService registerPlugin:@"PluginName" plugin:plugin];let plugin = EMASCustomPlugin()
miniAppService.registerPlugin("PluginName", plugin: plugin)4. Plugin retrieval.
import com.alibaba.module.android.mini.app.service.plugin.PluginService;
BasePlugin plugin = PluginService.getInstance().getPlugin("PluginName");EMASBasePlugin *plugin = [miniAppService getPlugin:@"PluginName"];let plugin = miniAppService.getPlugin("PluginName")5. Plugin startup.
import com.alibaba.module.android.mini.app.service.plugin.PluginService;
// Method 1
CustomPlugin customPlugin = new CustomPlugin(context, ...);
customPlugin.start();
// Method 2
BasePlugin plugin = PluginService.getInstance().getPlugin("PluginName");
plugin.start();
// Method 1
EMASCustomPlugin *plugin = [[EMASCustomPlugin alloc] init];
[miniAppService registerPlugin:@"PluginName" plugin:plugin];
[plugin start];
// Method 2
EMASBasePlugin *plugin = [miniAppService getPlugin:@"PluginName"];
[plugin start];
/// Method 1
let plugin = EMASCustomPlugin()
miniAppService.registerPlugin("PluginName", plugin: plugin)
plugin.start()
/// Method 2
let plugin = miniAppService.getPlugin("PluginName")
plugin.start()6. Retrieve LifeCycleService within the plugin.
import com.alibaba.emas.android.windvane.mini.app.pluginsdk.environment.PluginEnv;
import com.alibaba.emas.android.windvane.mini.app.pluginsdk.ILifeCycleService;
ILifeCycleService lifeCycleService = PluginEnv.getInstance().getContainerContext().getLifeCycleService()#import <EMASMiniAppService/EMASLifeCycleService.h>
#import <EMASMiniAppService/EMASIMiniAppEventObserver.h>
#import <EMASMiniAppService/EMASIMiniAppPageEventObserver.h>
@interface EMASCustomPlugin()<EMASIMiniAppEventObserver, EMASIMiniAppPageEventObserver>
@property(nonatomic, strong) EMASPluginContext *plugContext;
@end
@implementation EMASCustomPlugin
- (void)getlifeCycleService {
EMASLifeCycleService *lifeCycleService = self.plugContext.context.getLifeCycleService;
}@objc class EMASCustomPlugin: EMASBasePlugin, EMASIMiniAppEventObserver, EMASIMiniAppPageEventObserver {
var plugContext:EMASPluginContext?
func getlifeCycleService() {
let lifeCycleService = self.plugContext?.context.getLifeCycleService()
}
}III. Custom Reporting Plugin Development

1. Implement observer objects for MiniApp lifecycle events and MiniApp page lifecycle events
The miniApp parameters as follows:
user_id: userId, the userId parameter in the EMASUserInfoService(iOS),IUserInfoService(Android ) registered by container initialization.
mini_app_id: the appId of the opened miniapp.
mini_app_version: the version of the opened miniapp.
mini_app_type: the type of the opened miniapp, such as windvane or uniapp.
app_code: the appCode passed in when the container is initialized.
timestamp: page triggers current timestamp.
import com.alibaba.emas.android.windvane.mini.app.pluginsdk.observer.IMiniAppEventObserver;
import com.alibaba.emas.android.windvane.mini.app.pluginsdk.observer.IMiniAppPageEventObserver;
import com.alibaba.emas.android.windvane.mini.app.pluginsdk.plugin.BasePlugin;
public class CustomReportPlugin extends BasePlugin implements IMiniAppEventObserver, IMiniAppPageEventObserver {
// Implement MiniApp lifecycle event callback
@Override
void onMiniAppStart(Map<String, Object> params) {
String userId = (String) params.get("user_id");
String appId = (String) params.get("mini_app_id");
String version = (String) params.get("mini_app_version");
String appType = (String) params.get("mini_app_type");
String appCode = (String) params.get("app_code");
String timestamp = (String) params.get("timestamp");
...
}
@Override
void onMiniAppClose(Map<String, Object> params) {
String userId = (String) params.get("user_id");
String appId = (String) params.get("mini_app_id");
String version = (String) params.get("mini_app_version");
String appType = (String) params.get("mini_app_type");
String appCode = (String) params.get("app_code");
String timestamp = (String) params.get("timestamp");
...
}
@Override
void onMiniAppShow(Map<String, Object> params) {
String userId = (String) params.get("user_id");
String appId = (String) params.get("mini_app_id");
String version = (String) params.get("mini_app_version");
String appType = (String) params.get("mini_app_type");
String appCode = (String) params.get("app_code");
String timestamp = (String) params.get("timestamp");
...
}
@Override
void onMiniAppHide(Map<String, Object> params) {
String userId = (String) params.get("user_id");
String appId = (String) params.get("mini_app_id");
String version = (String) params.get("mini_app_version");
String appType = (String) params.get("mini_app_type");
String appCode = (String) params.get("app_code");
String timestamp = (String) params.get("timestamp");
...
}
// Implementing lifecycle event callbacks for MiniApp pages
void onPageStart(Map<String, Object> params) {
String url = (String) params.get("url");
String fullUrl = (String) params.get("fullUrl");
String title = (String) params.get("title");
String referrer = (String) params.get("referrer");
String userAgent = (String) params.get("userAgent");
double viewportWidth = (double) params.get("viewportWidth");
double viewportHeight = (double) params.get("viewportHeight");
String userId = (String) params.get("user_id");
String appId = (String) params.get("mini_app_id");
String version = (String) params.get("mini_app_version");
String appType = (String) params.get("mini_app_type");
String appCode = (String) params.get("app_code");
String timestamp = (String) params.get("timestamp");
...
}
void onPageHide(Map<String, Object> params) {
String url = (String) params.get("url");
String fullUrl = (String) params.get("fullUrl");
String title = (String) params.get("title");
String referrer = (String) params.get("referrer");
String userAgent = (String) params.get("userAgent");
double viewportWidth = (double) params.get("viewportWidth");
double viewportHeight = (double) params.get("viewportHeight");
String userId = (String) params.get("user_id");
String appId = (String) params.get("mini_app_id");
String version = (String) params.get("mini_app_version");
String appType = (String) params.get("mini_app_type");
String appCode = (String) params.get("app_code");
String timestamp = (String) params.get("timestamp");
...
}
void onPageShow(Map<String, Object> params) {
String url = (String) params.get("url");
String fullUrl = (String) params.get("fullUrl");
String title = (String) params.get("title");
String referrer = (String) params.get("referrer");
String userAgent = (String) params.get("userAgent");
double viewportWidth = (double) params.get("viewportWidth");
double viewportHeight = (double) params.get("viewportHeight");
String userId = (String) params.get("user_id");
String appId = (String) params.get("mini_app_id");
String version = (String) params.get("mini_app_version");
String appType = (String) params.get("mini_app_type");
String appCode = (String) params.get("app_code");
String timestamp = (String) params.get("timestamp");
...
}
void onPageEnd(Map<String, Object> params) {
String url = (String) params.get("url");
String fullUrl = (String) params.get("fullUrl");
String title = (String) params.get("title");
String referrer = (String) params.get("referrer");
String userAgent = (String) params.get("userAgent");
double viewportWidth = (double) params.get("viewportWidth");
double viewportHeight = (double) params.get("viewportHeight");
String userId = (String) params.get("user_id");
String appId = (String) params.get("mini_app_id");
String version = (String) params.get("mini_app_version");
String appType = (String) params.get("mini_app_type");
String appCode = (String) params.get("app_code");
String timestamp = (String) params.get("timestamp");
...
}
}@interface EMASCustomPlugin()<EMASIMiniAppEventObserver, EMASIMiniAppPageEventObserver>
@property(nonatomic, strong) EMASPluginContext *plugContext;
@end
@implementation EMASCustomPlugin
#pragma mark -EMASIMiniAppEventObserver
- (void)onMiniAppStart:(NSDictionary *)params {
NSString *appId = [params objectForKey:@"mini_app_id"];
NSString *appType = [params objectForKey:@"mini_app_type"];
NSString *userId = [params objectForKey:@"user_id"];
NSString *version = [params objectForKey:@"mini_app_version"];
NSString *appCode = [params objectForKey:@"app_code"];
NSString *timestamp = [params objectForKey:@"timestamp"];
...
}
-(void)onMiniAppShow:(NSDictionary *)params {
NSString *appId = [params objectForKey:@"mini_app_id"];
NSString *appType = [params objectForKey:@"mini_app_type"];
NSString *userId = [params objectForKey:@"user_id"];
NSString *version = [params objectForKey:@"mini_app_version"];
NSString *appCode = [params objectForKey:@"app_code"];
NSString *timestamp = [params objectForKey:@"timestamp"];
...
}
- (void)onMiniAppHide:(NSDictionary *)params {
NSString *appId = [params objectForKey:@"mini_app_id"];
NSString *appType = [params objectForKey:@"mini_app_type"];
NSString *userId = [params objectForKey:@"user_id"];
NSString *version = [params objectForKey:@"mini_app_version"];
NSString *appCode = [params objectForKey:@"app_code"];
NSString *timestamp = [params objectForKey:@"timestamp"];
...
}
- (void)onMiniAppClose:(NSDictionary *)params {
NSString *appId = [params objectForKey:@"mini_app_id"];
NSString *appType = [params objectForKey:@"mini_app_type"];
NSString *userId = [params objectForKey:@"user_id"];
NSString *version = [params objectForKey:@"mini_app_version"];
NSString *appCode = [params objectForKey:@"app_code"];
NSString *timestamp = [params objectForKey:@"timestamp"];
...
}
#pragma mark -EMASIMiniAppPageEventObserver
- (void)onPageStart:(NSDictionary *)params {
NSString *url = [params objectForKey:@"url"];
NSString *fullUrl = [params objectForKey:@"fullUrl"];
NSString *title = [params objectForKey:@"title"];
NSString *referrer = [params objectForKey:@"referrer"];
NSString *userAgent = [params objectForKey:@"userAgent"];
double viewportWidth = [params objectForKey:@"viewportWidth"];
double viewportHeight = [params objectForKey:@"viewportHeight"];
NSString *appId = [params objectForKey:@"mini_app_id"];
NSString *appType = [params objectForKey:@"mini_app_type"];
NSString *userId = [params objectForKey:@"user_id"];
NSString *version = [params objectForKey:@"mini_app_version"];
NSString *appCode = [params objectForKey:@"app_code"];
NSString *timestamp = [params objectForKey:@"timestamp"];
...
}
- (void)onPageShow:(NSDictionary *)params {
NSString *url = [params objectForKey:@"url"];
NSString *fullUrl = [params objectForKey:@"fullUrl"];
NSString *title = [params objectForKey:@"title"];
NSString *referrer = [params objectForKey:@"referrer"];
NSString *userAgent = [params objectForKey:@"userAgent"];
double viewportWidth = [params objectForKey:@"viewportWidth"];
double viewportHeight = [params objectForKey:@"viewportHeight"];
NSString *appId = [params objectForKey:@"mini_app_id"];
NSString *appType = [params objectForKey:@"mini_app_type"];
NSString *userId = [params objectForKey:@"user_id"];
NSString *version = [params objectForKey:@"mini_app_version"];
NSString *appCode = [params objectForKey:@"app_code"];
NSString *timestamp = [params objectForKey:@"timestamp"];
...
}
- (void)onPageHide:(NSDictionary *)params {
NSString *url = [params objectForKey:@"url"];
NSString *fullUrl = [params objectForKey:@"fullUrl"];
NSString *title = [params objectForKey:@"title"];
NSString *referrer = [params objectForKey:@"referrer"];
NSString *userAgent = [params objectForKey:@"userAgent"];
double viewportWidth = [params objectForKey:@"viewportWidth"];
double viewportHeight = [params objectForKey:@"viewportHeight"];
NSString *appId = [params objectForKey:@"mini_app_id"];
NSString *appType = [params objectForKey:@"mini_app_type"];
NSString *userId = [params objectForKey:@"user_id"];
NSString *version = [params objectForKey:@"mini_app_version"];
NSString *appCode = [params objectForKey:@"app_code"];
NSString *timestamp = [params objectForKey:@"timestamp"];
...
}
- (void)onPageEnd:(NSDictionary *)params {
// This method is not called on the iOS
}import UIKit
import EMASMiniAppService
@objc class EMASCustomPlugin: EMASBasePlugin, EMASIMiniAppEventObserver, EMASIMiniAppPageEventObserver {
var plugContext:EMASPluginContext?
///EMASIMiniAppEventObserver
func onMiniAppStart(_ params: [AnyHashable : Any]) {
let appId = params["mini_app_id"] as? String
let appType = params["mini_app_type"] as? String
let userId = params["user_id"] as? String
let version = params["mini_app_version"] as? String
let appCode = params["app_code"] as? String
let timestamp = params["timestamp"] as? String
}
func onMiniAppShow(_ params: [AnyHashable : Any]) {
let appId = params["mini_app_id"] as? String
let appType = params["mini_app_type"] as? String
let userId = params["user_id"] as? String
let version = params["mini_app_version"] as? String
let appCode = params["app_code"] as? String
let timestamp = params["timestamp"] as? String
}
func onMiniAppHide(_ params: [AnyHashable : Any]) {
let appId = params["mini_app_id"] as? String
let appType = params["mini_app_type"] as? String
let userId = params["user_id"] as? String
let version = params["mini_app_version"] as? String
let appCode = params["app_code"] as? String
let timestamp = params["timestamp"] as? String
}
func onMiniAppClose(_ params: [AnyHashable : Any]) {
let appId = params["mini_app_id"] as? String
let appType = params["mini_app_type"] as? String
let userId = params["user_id"] as? String
let version = params["mini_app_version"] as? String
let appCode = params["app_code"] as? String
let timestamp = params["timestamp"] as? String
}
///EMASIMiniAppPageEventObserver
func onPageStart(_ params: [AnyHashable : Any]) {
let url = params["url"] as? String
let fullUrl = params["fullUrl"] as? String
let title = params["title"] as? String
let referrer = params["referrer"] as? String
let userAgent = params["userAgent"] as? String
let viewportWidth = params["viewportWidth"] as? Double
let viewportHeight = params["viewportHeight"] as? Double
let appId = params["mini_app_id"] as? String
let appType = params["mini_app_type"] as? String
let userId = params["user_id"] as? String
let version = params["mini_app_version"] as? String
let appCode = params["app_code"] as? String
let timestamp = params["timestamp"] as? String
}
func onPageShow(_ params: [AnyHashable : Any]) {
let url = params["url"] as? String
let fullUrl = params["fullUrl"] as? String
let title = params["title"] as? String
let referrer = params["referrer"] as? String
let userAgent = params["userAgent"] as? String
let viewportWidth = params["viewportWidth"] as? Double
let viewportHeight = params["viewportHeight"] as? Double
let appId = params["mini_app_id"] as? String
let appType = params["mini_app_type"] as? String
let userId = params["user_id"] as? String
let version = params["mini_app_version"] as? String
let appCode = params["app_code"] as? String
let timestamp = params["timestamp"] as? String
}
func onPageHide(_ params: [AnyHashable : Any]) {
let url = params["url"] as? String
let fullUrl = params["fullUrl"] as? String
let title = params["title"] as? String
let referrer = params["referrer"] as? String
let userAgent = params["userAgent"] as? String
let viewportWidth = params["viewportWidth"] as? Double
let viewportHeight = params["viewportHeight"] as? Double
let appId = params["mini_app_id"] as? String
let appType = params["mini_app_type"] as? String
let userId = params["user_id"] as? String
let version = params["mini_app_version"] as? String
let appCode = params["app_code"] as? String
let timestamp = params["timestamp"] as? String
}
func onPageEnd(_ params: [AnyHashable : Any]) {
/// This method is not called on the iOS
}
}2. Registered Observer Object
import com.alibaba.emas.android.windvane.mini.app.pluginsdk.environment.PluginEnv;
public class CustomReportPlugin extends BasePlugin implements IMiniAppEventObserver, IMiniAppPageEventObserver {
private void registerObserver() {
PluginEnv.getInstance().getContainerContext().getLifeCycleService().registerMiniAppObserver(this);
PluginEnv.getInstance().getContainerContext().getLifeCycleService().registerMiniPageObserver(this);
}
}
#import <EMASMiniAppService/EMASIMiniAppEventObserver.h>
#import <EMASMiniAppService/EMASIMiniAppPageEventObserver.h>
@interface EMASCustomPlugin()<EMASIMiniAppEventObserver, EMASIMiniAppPageEventObserver>
@property(nonatomic, strong) EMASPluginContext *plugContext;
@end
@implementation EMASCustomPlugin
- (void)registerObserver {
[self.plugContext.context.getLifeCycleService registerMiniAppObserver:self];
[self.plugContext.context.getLifeCycleService registerMiniPageObserver:self];
}import UIKit
import EMASMiniAppService
@objc class EMASCustomPlugin: EMASBasePlugin, EMASIMiniAppEventObserver, EMASIMiniAppPageEventObserver {
var plugContext:EMASPluginContext?
func registerObserver() {
self.plugContext?.context.getLifeCycleService().registerMiniAppObserver(self)
self.plugContext?.context.getLifeCycleService().registerMiniPageObserver(self)
}
}3. Register, Retrieve, and Start Plugins
For details, see sections 2.3 to 2.5.
4. Other MiniApp Events
Custom jsapi
IV. Notes
After opening the miniapp interface,
onPageShowwill be called twice.On iOS, the miniapp closing will not trigger the
onPageEndevent (you need to call the page closing method within the miniapp closing method).