0
# Analytics
1
2
Comprehensive analytics and data insights including user trends, visit patterns, retention analysis, user demographics, and performance metrics for WeChat MiniApp data-driven decision making.
3
4
## Capabilities
5
6
### Analytics Service Interface
7
8
Core analytics operations providing detailed insights into mini program usage and user behavior.
9
10
```java { .api }
11
public interface WxMaAnalysisService {
12
// Overview Trends
13
List<WxMaSummaryTrend> getDailySummaryTrend(Date beginDate, Date endDate) throws WxErrorException;
14
15
// Visit Trends
16
List<WxMaVisitTrend> getDailyVisitTrend(Date beginDate, Date endDate) throws WxErrorException;
17
List<WxMaVisitTrend> getWeeklyVisitTrend(Date beginDate, Date endDate) throws WxErrorException;
18
List<WxMaVisitTrend> getMonthlyVisitTrend(Date beginDate, Date endDate) throws WxErrorException;
19
20
// User Analysis
21
WxMaVisitDistribution getVisitDistribution(Date beginDate, Date endDate) throws WxErrorException;
22
WxMaRetainInfo getDailyRetainInfo(Date beginDate, Date endDate) throws WxErrorException;
23
WxMaRetainInfo getWeeklyRetainInfo(Date beginDate, Date endDate) throws WxErrorException;
24
WxMaRetainInfo getMonthlyRetainInfo(Date beginDate, Date endDate) throws WxErrorException;
25
26
// Page Analysis
27
List<WxMaVisitPage> getVisitPage(Date beginDate, Date endDate) throws WxErrorException;
28
29
// User Demographics
30
WxMaUserPortrait getUserPortrait(Date beginDate, Date endDate) throws WxErrorException;
31
}
32
```
33
34
### Analytics Data Models
35
36
Comprehensive data models for different types of analytics and metrics.
37
38
```java { .api }
39
public class WxMaSummaryTrend implements Serializable {
40
private String refDate; // Reference date (YYYYMMDD format)
41
private Integer visitTotal; // Total visits
42
private Integer shareUv; // Unique users who shared
43
private Integer sharePv; // Total shares
44
45
// Getters and setters
46
public String getRefDate();
47
public void setRefDate(String refDate);
48
public Integer getVisitTotal();
49
public void setVisitTotal(Integer visitTotal);
50
public Integer getShareUv();
51
public void setShareUv(Integer shareUv);
52
public Integer getSharePv();
53
public void setSharePv(Integer sharePv);
54
55
// Utility methods
56
public Date getRefDateAsDate();
57
public static WxMaSummaryTrend fromJson(String json);
58
public String toJson();
59
}
60
```
61
62
```java { .api }
63
public class WxMaVisitTrend implements Serializable {
64
private String refDate; // Reference date
65
private Integer sessionCnt; // Session count
66
private Integer visitPv; // Page views
67
private Integer visitUv; // Unique visitors
68
private Integer visitUvNew; // New unique visitors
69
private Float stayTimeUv; // Average stay time per user
70
private Float stayTimeSession; // Average stay time per session
71
private Float visitDepth; // Average visit depth
72
73
// Getters and setters
74
public String getRefDate();
75
public void setRefDate(String refDate);
76
public Integer getSessionCnt();
77
public void setSessionCnt(Integer sessionCnt);
78
public Integer getVisitPv();
79
public void setVisitPv(Integer visitPv);
80
public Integer getVisitUv();
81
public void setVisitUv(Integer visitUv);
82
public Integer getVisitUvNew();
83
public void setVisitUvNew(Integer visitUvNew);
84
public Float getStayTimeUv();
85
public void setStayTimeUv(Float stayTimeUv);
86
public Float getStayTimeSession();
87
public void setStayTimeSession(Float stayTimeSession);
88
public Float getVisitDepth();
89
public void setVisitDepth(Float visitDepth);
90
91
// Utility methods
92
public Date getRefDateAsDate();
93
public static WxMaVisitTrend fromJson(String json);
94
}
95
```
96
97
```java { .api }
98
public class WxMaVisitDistribution implements Serializable {
99
private String refDate; // Reference date
100
private List<AccessSource> accessSource; // Traffic sources
101
102
public static class AccessSource {
103
private String accessSourceName; // Source name
104
private Integer accessSourceVisitUv; // Unique visitors from source
105
106
public String getAccessSourceName();
107
public void setAccessSourceName(String accessSourceName);
108
public Integer getAccessSourceVisitUv();
109
public void setAccessSourceVisitUv(Integer accessSourceVisitUv);
110
}
111
112
// Getters and setters
113
public String getRefDate();
114
public void setRefDate(String refDate);
115
public List<AccessSource> getAccessSource();
116
public void setAccessSource(List<AccessSource> accessSource);
117
}
118
```
119
120
```java { .api }
121
public class WxMaRetainInfo implements Serializable {
122
private String refDate; // Reference date
123
private List<RetainInfo> visitRetainInfo; // Retention data
124
125
public static class RetainInfo {
126
private Integer key; // Day offset (0, 1, 2, 3...)
127
private Float value; // Retention rate (0-1)
128
129
public Integer getKey();
130
public void setKey(Integer key);
131
public Float getValue();
132
public void setValue(Float value);
133
}
134
135
// Getters and setters
136
public String getRefDate();
137
public void setRefDate(String refDate);
138
public List<RetainInfo> getVisitRetainInfo();
139
public void setVisitRetainInfo(List<RetainInfo> visitRetainInfo);
140
141
// Convenience methods
142
public Float getRetentionRate(int dayOffset);
143
public Map<Integer, Float> getRetentionMap();
144
}
145
```
146
147
```java { .api }
148
public class WxMaVisitPage implements Serializable {
149
private String refDate; // Reference date
150
private String pagePath; // Page path
151
private Integer visitPv; // Page views
152
private Integer visitUv; // Unique visitors
153
private Float stayTimeUv; // Average stay time per user
154
private Float entryPagePv; // Entry page views
155
private Float exitPagePv; // Exit page views
156
private Float shareUv; // Share unique users
157
private Float sharePv; // Share page views
158
159
// Getters and setters
160
public String getRefDate();
161
public void setRefDate(String refDate);
162
public String getPagePath();
163
public void setPagePath(String pagePath);
164
public Integer getVisitPv();
165
public void setVisitPv(Integer visitPv);
166
public Integer getVisitUv();
167
public void setVisitUv(Integer visitUv);
168
public Float getStayTimeUv();
169
public void setStayTimeUv(Float stayTimeUv);
170
public Float getEntryPagePv();
171
public void setEntryPagePv(Float entryPagePv);
172
public Float getExitPagePv();
173
public void setExitPagePv(Float exitPagePv);
174
public Float getShareUv();
175
public void setShareUv(Float shareUv);
176
public Float getSharePv();
177
public void setSharePv(Float sharePv);
178
}
179
```
180
181
```java { .api }
182
public class WxMaUserPortrait implements Serializable {
183
private String refDate; // Reference date
184
private List<VisitUvNew> visitUvNew; // New user demographics
185
186
public static class VisitUvNew {
187
private Integer index; // Index identifier
188
private String province; // Province
189
private String city; // City
190
private Integer genders; // Gender (0: unknown, 1: male, 2: female)
191
private String platforms; // Platform (iPhone, Android, etc.)
192
private String devices; // Device model
193
private String ages; // Age range
194
private Integer value; // User count
195
196
// Getters and setters
197
public Integer getIndex();
198
public void setIndex(Integer index);
199
public String getProvince();
200
public void setProvince(String province);
201
public String getCity();
202
public void setCity(String city);
203
public Integer getGenders();
204
public void setGenders(Integer genders);
205
public String getPlatforms();
206
public void setPlatforms(String platforms);
207
public String getDevices();
208
public void setDevices(String devices);
209
public String getAges();
210
public void setAges(String ages);
211
public Integer getValue();
212
public void setValue(Integer value);
213
}
214
215
// Getters and setters
216
public String getRefDate();
217
public void setRefDate(String refDate);
218
public List<VisitUvNew> getVisitUvNew();
219
public void setVisitUvNew(List<VisitUvNew> visitUvNew);
220
221
// Analysis methods
222
public Map<String, Integer> getGenderDistribution();
223
public Map<String, Integer> getPlatformDistribution();
224
public Map<String, Integer> getLocationDistribution();
225
}
226
```
227
228
## Usage Examples
229
230
### Daily Analytics Overview
231
232
```java
233
@Service
234
public class AnalyticsService {
235
236
@Autowired
237
private WxMaService wxMaService;
238
239
public DailyAnalyticsReport getDailyReport(Date targetDate) {
240
try {
241
Date endDate = targetDate;
242
Date startDate = DateUtils.addDays(targetDate, -30); // Last 30 days
243
244
// Get summary trends
245
List<WxMaSummaryTrend> summaryTrends = wxMaService.getAnalysisService()
246
.getDailySummaryTrend(startDate, endDate);
247
248
// Get visit trends
249
List<WxMaVisitTrend> visitTrends = wxMaService.getAnalysisService()
250
.getDailyVisitTrend(startDate, endDate);
251
252
// Get traffic sources
253
WxMaVisitDistribution distribution = wxMaService.getAnalysisService()
254
.getVisitDistribution(startDate, endDate);
255
256
// Get top pages
257
List<WxMaVisitPage> topPages = wxMaService.getAnalysisService()
258
.getVisitPage(startDate, endDate);
259
260
return new DailyAnalyticsReport(summaryTrends, visitTrends, distribution, topPages);
261
262
} catch (WxErrorException e) {
263
logger.error("Failed to get daily analytics: {}", e.getMessage());
264
throw new AnalyticsException("Could not retrieve daily analytics", e);
265
}
266
}
267
}
268
```
269
270
### User Retention Analysis
271
272
```java
273
public class RetentionAnalyzer {
274
275
public RetentionReport analyzeRetention(Date startDate, int days) {
276
try {
277
Date endDate = DateUtils.addDays(startDate, days - 1);
278
279
// Get daily retention
280
WxMaRetainInfo dailyRetention = wxMaService.getAnalysisService()
281
.getDailyRetainInfo(startDate, endDate);
282
283
// Get weekly retention
284
WxMaRetainInfo weeklyRetention = wxMaService.getAnalysisService()
285
.getWeeklyRetainInfo(startDate, endDate);
286
287
// Get monthly retention
288
WxMaRetainInfo monthlyRetention = wxMaService.getAnalysisService()
289
.getMonthlyRetainInfo(startDate, endDate);
290
291
// Analyze retention patterns
292
RetentionReport report = new RetentionReport();
293
report.setDailyRetention(analyzeRetentionData(dailyRetention));
294
report.setWeeklyRetention(analyzeRetentionData(weeklyRetention));
295
report.setMonthlyRetention(analyzeRetentionData(monthlyRetention));
296
297
// Calculate key metrics
298
report.setDay1Retention(dailyRetention.getRetentionRate(1));
299
report.setDay7Retention(dailyRetention.getRetentionRate(7));
300
report.setDay30Retention(dailyRetention.getRetentionRate(30));
301
302
return report;
303
304
} catch (WxErrorException e) {
305
logger.error("Retention analysis failed: {}", e.getMessage());
306
throw new AnalyticsException("Retention analysis failed", e);
307
}
308
}
309
310
private Map<String, Object> analyzeRetentionData(WxMaRetainInfo retentionInfo) {
311
Map<String, Object> analysis = new HashMap<>();
312
Map<Integer, Float> retentionMap = retentionInfo.getRetentionMap();
313
314
// Calculate retention trend
315
List<Float> rates = new ArrayList<>(retentionMap.values());
316
analysis.put("trend", calculateTrend(rates));
317
analysis.put("avgRetention", calculateAverage(rates));
318
analysis.put("retentionCurve", retentionMap);
319
320
return analysis;
321
}
322
}
323
```
324
325
### Traffic Source Analysis
326
327
```java
328
@Component
329
public class TrafficAnalyzer {
330
331
public TrafficSourceReport analyzeTrafficSources(Date startDate, Date endDate) {
332
try {
333
WxMaVisitDistribution distribution = wxMaService.getAnalysisService()
334
.getVisitDistribution(startDate, endDate);
335
336
List<WxMaVisitDistribution.AccessSource> sources = distribution.getAccessSource();
337
338
// Calculate total traffic
339
int totalVisitors = sources.stream()
340
.mapToInt(WxMaVisitDistribution.AccessSource::getAccessSourceVisitUv)
341
.sum();
342
343
// Analyze each source
344
Map<String, SourceAnalysis> sourceAnalysis = new HashMap<>();
345
for (WxMaVisitDistribution.AccessSource source : sources) {
346
SourceAnalysis analysis = new SourceAnalysis();
347
analysis.setName(source.getAccessSourceName());
348
analysis.setVisitors(source.getAccessSourceVisitUv());
349
analysis.setPercentage((float) source.getAccessSourceVisitUv() / totalVisitors * 100);
350
351
sourceAnalysis.put(source.getAccessSourceName(), analysis);
352
}
353
354
// Identify top sources
355
List<SourceAnalysis> topSources = sourceAnalysis.values().stream()
356
.sorted((a, b) -> Integer.compare(b.getVisitors(), a.getVisitors()))
357
.limit(10)
358
.collect(Collectors.toList());
359
360
TrafficSourceReport report = new TrafficSourceReport();
361
report.setTotalVisitors(totalVisitors);
362
report.setSourceBreakdown(sourceAnalysis);
363
report.setTopSources(topSources);
364
report.setReportDate(distribution.getRefDate());
365
366
return report;
367
368
} catch (WxErrorException e) {
369
logger.error("Traffic source analysis failed: {}", e.getMessage());
370
throw new AnalyticsException("Traffic analysis failed", e);
371
}
372
}
373
}
374
```
375
376
### Page Performance Analysis
377
378
```java
379
public class PagePerformanceAnalyzer {
380
381
public PagePerformanceReport analyzePagePerformance(Date startDate, Date endDate) {
382
try {
383
List<WxMaVisitPage> pages = wxMaService.getAnalysisService()
384
.getVisitPage(startDate, endDate);
385
386
// Sort pages by different metrics
387
List<WxMaVisitPage> topPagesByViews = pages.stream()
388
.sorted((a, b) -> Integer.compare(b.getVisitPv(), a.getVisitPv()))
389
.limit(20)
390
.collect(Collectors.toList());
391
392
List<WxMaVisitPage> topPagesByUniqueVisitors = pages.stream()
393
.sorted((a, b) -> Integer.compare(b.getVisitUv(), a.getVisitUv()))
394
.limit(20)
395
.collect(Collectors.toList());
396
397
List<WxMaVisitPage> topPagesByEngagement = pages.stream()
398
.filter(p -> p.getStayTimeUv() != null)
399
.sorted((a, b) -> Float.compare(b.getStayTimeUv(), a.getStayTimeUv()))
400
.limit(20)
401
.collect(Collectors.toList());
402
403
// Calculate performance metrics
404
Map<String, PageMetrics> pageMetrics = new HashMap<>();
405
for (WxMaVisitPage page : pages) {
406
PageMetrics metrics = new PageMetrics();
407
metrics.setPath(page.getPagePath());
408
metrics.setPageViews(page.getVisitPv());
409
metrics.setUniqueVisitors(page.getVisitUv());
410
metrics.setAvgStayTime(page.getStayTimeUv());
411
metrics.setBounceRate(calculateBounceRate(page));
412
metrics.setShareRate(calculateShareRate(page));
413
414
pageMetrics.put(page.getPagePath(), metrics);
415
}
416
417
PagePerformanceReport report = new PagePerformanceReport();
418
report.setTopPagesByViews(topPagesByViews);
419
report.setTopPagesByUniqueVisitors(topPagesByUniqueVisitors);
420
report.setTopPagesByEngagement(topPagesByEngagement);
421
report.setPageMetrics(pageMetrics);
422
423
return report;
424
425
} catch (WxErrorException e) {
426
logger.error("Page performance analysis failed: {}", e.getMessage());
427
throw new AnalyticsException("Page analysis failed", e);
428
}
429
}
430
431
private Float calculateBounceRate(WxMaVisitPage page) {
432
if (page.getEntryPagePv() != null && page.getEntryPagePv() > 0) {
433
return (page.getExitPagePv() / page.getEntryPagePv()) * 100;
434
}
435
return null;
436
}
437
438
private Float calculateShareRate(WxMaVisitPage page) {
439
if (page.getVisitUv() != null && page.getVisitUv() > 0 && page.getShareUv() != null) {
440
return (page.getShareUv() / page.getVisitUv()) * 100;
441
}
442
return null;
443
}
444
}
445
```
446
447
### User Demographics Analysis
448
449
```java
450
@Component
451
public class UserDemographicsAnalyzer {
452
453
public DemographicsReport analyzeDemographics(Date startDate, Date endDate) {
454
try {
455
WxMaUserPortrait portrait = wxMaService.getAnalysisService()
456
.getUserPortrait(startDate, endDate);
457
458
List<WxMaUserPortrait.VisitUvNew> userData = portrait.getVisitUvNew();
459
460
// Analyze gender distribution
461
Map<String, Integer> genderDist = analyzeGenderDistribution(userData);
462
463
// Analyze platform distribution
464
Map<String, Integer> platformDist = analyzePlatformDistribution(userData);
465
466
// Analyze geographic distribution
467
Map<String, Integer> geoDist = analyzeGeographicDistribution(userData);
468
469
// Analyze age distribution
470
Map<String, Integer> ageDist = analyzeAgeDistribution(userData);
471
472
// Analyze device distribution
473
Map<String, Integer> deviceDist = analyzeDeviceDistribution(userData);
474
475
DemographicsReport report = new DemographicsReport();
476
report.setGenderDistribution(genderDist);
477
report.setPlatformDistribution(platformDist);
478
report.setGeographicDistribution(geoDist);
479
report.setAgeDistribution(ageDist);
480
report.setDeviceDistribution(deviceDist);
481
report.setTotalNewUsers(userData.stream().mapToInt(WxMaUserPortrait.VisitUvNew::getValue).sum());
482
report.setReportDate(portrait.getRefDate());
483
484
return report;
485
486
} catch (WxErrorException e) {
487
logger.error("Demographics analysis failed: {}", e.getMessage());
488
throw new AnalyticsException("Demographics analysis failed", e);
489
}
490
}
491
492
private Map<String, Integer> analyzeGenderDistribution(List<WxMaUserPortrait.VisitUvNew> userData) {
493
Map<String, Integer> distribution = new HashMap<>();
494
495
for (WxMaUserPortrait.VisitUvNew user : userData) {
496
String gender = getGenderLabel(user.getGenders());
497
distribution.merge(gender, user.getValue(), Integer::sum);
498
}
499
500
return distribution;
501
}
502
503
private String getGenderLabel(Integer genderCode) {
504
switch (genderCode) {
505
case 1: return "Male";
506
case 2: return "Female";
507
default: return "Unknown";
508
}
509
}
510
511
private Map<String, Integer> analyzeGeographicDistribution(List<WxMaUserPortrait.VisitUvNew> userData) {
512
Map<String, Integer> distribution = new HashMap<>();
513
514
for (WxMaUserPortrait.VisitUvNew user : userData) {
515
String location = user.getProvince();
516
if (location != null && !location.isEmpty()) {
517
distribution.merge(location, user.getValue(), Integer::sum);
518
}
519
}
520
521
return distribution.entrySet().stream()
522
.sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
523
.limit(20)
524
.collect(Collectors.toMap(
525
Map.Entry::getKey,
526
Map.Entry::getValue,
527
(e1, e2) -> e1,
528
LinkedHashMap::new
529
));
530
}
531
}
532
```
533
534
### Real-time Analytics Dashboard
535
536
```java
537
@RestController
538
@RequestMapping("/api/analytics")
539
public class AnalyticsDashboardController {
540
541
@GetMapping("/dashboard")
542
public ResponseEntity<AnalyticsDashboard> getDashboard(
543
@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") Date startDate,
544
@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") Date endDate) {
545
546
try {
547
AnalyticsDashboard dashboard = new AnalyticsDashboard();
548
549
// Get overview metrics
550
List<WxMaSummaryTrend> summary = wxMaService.getAnalysisService()
551
.getDailySummaryTrend(startDate, endDate);
552
553
List<WxMaVisitTrend> visits = wxMaService.getAnalysisService()
554
.getDailyVisitTrend(startDate, endDate);
555
556
// Calculate key metrics
557
dashboard.setTotalVisits(summary.stream().mapToInt(WxMaSummaryTrend::getVisitTotal).sum());
558
dashboard.setTotalUniqueVisitors(visits.stream().mapToInt(WxMaVisitTrend::getVisitUv).sum());
559
dashboard.setTotalPageViews(visits.stream().mapToInt(WxMaVisitTrend::getVisitPv).sum());
560
dashboard.setAvgSessionDuration(visits.stream()
561
.filter(v -> v.getStayTimeSession() != null)
562
.mapToDouble(WxMaVisitTrend::getStayTimeSession)
563
.average().orElse(0.0));
564
565
// Get retention data
566
WxMaRetainInfo retention = wxMaService.getAnalysisService()
567
.getDailyRetainInfo(startDate, endDate);
568
dashboard.setRetentionData(retention.getRetentionMap());
569
570
// Get traffic sources
571
WxMaVisitDistribution traffic = wxMaService.getAnalysisService()
572
.getVisitDistribution(startDate, endDate);
573
dashboard.setTrafficSources(traffic.getAccessSource());
574
575
// Get top pages
576
List<WxMaVisitPage> topPages = wxMaService.getAnalysisService()
577
.getVisitPage(startDate, endDate);
578
dashboard.setTopPages(topPages.stream()
579
.sorted((a, b) -> Integer.compare(b.getVisitPv(), a.getVisitPv()))
580
.limit(10)
581
.collect(Collectors.toList()));
582
583
return ResponseEntity.ok(dashboard);
584
585
} catch (WxErrorException e) {
586
logger.error("Dashboard data retrieval failed: {}", e.getMessage());
587
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
588
}
589
}
590
}
591
```
592
593
### Automated Analytics Reports
594
595
```java
596
@Component
597
public class AutomatedReportingService {
598
599
@Scheduled(cron = "0 0 9 * * ?") // Daily at 9 AM
600
public void generateDailyReport() {
601
Date yesterday = DateUtils.addDays(new Date(), -1);
602
Date lastWeek = DateUtils.addDays(yesterday, -6);
603
604
try {
605
// Generate comprehensive daily report
606
DailyReport report = new DailyReport();
607
608
// Get yesterday's data
609
List<WxMaSummaryTrend> summary = wxMaService.getAnalysisService()
610
.getDailySummaryTrend(yesterday, yesterday);
611
612
List<WxMaVisitTrend> visits = wxMaService.getAnalysisService()
613
.getDailyVisitTrend(yesterday, yesterday);
614
615
// Get week-over-week comparison
616
List<WxMaVisitTrend> weekTrend = wxMaService.getAnalysisService()
617
.getDailyVisitTrend(lastWeek, yesterday);
618
619
report.setDate(yesterday);
620
report.setSummary(summary.get(0));
621
report.setVisits(visits.get(0));
622
report.setWeeklyComparison(calculateWeeklyGrowth(weekTrend));
623
624
// Send report via email/notification
625
reportNotificationService.sendDailyReport(report);
626
627
} catch (WxErrorException e) {
628
logger.error("Failed to generate daily report: {}", e.getMessage());
629
}
630
}
631
632
@Scheduled(cron = "0 0 10 ? * MON") // Weekly on Monday at 10 AM
633
public void generateWeeklyReport() {
634
Date endDate = DateUtils.addDays(new Date(), -1);
635
Date startDate = DateUtils.addDays(endDate, -6);
636
637
try {
638
WeeklyReport report = new WeeklyReport();
639
640
// Get weekly analytics data
641
List<WxMaVisitTrend> weeklyData = wxMaService.getAnalysisService()
642
.getWeeklyVisitTrend(startDate, endDate);
643
644
WxMaRetainInfo retention = wxMaService.getAnalysisService()
645
.getWeeklyRetainInfo(startDate, endDate);
646
647
List<WxMaVisitPage> pagePerformance = wxMaService.getAnalysisService()
648
.getVisitPage(startDate, endDate);
649
650
WxMaUserPortrait demographics = wxMaService.getAnalysisService()
651
.getUserPortrait(startDate, endDate);
652
653
report.setWeeklyTrends(weeklyData);
654
report.setRetentionAnalysis(retention);
655
report.setTopPages(pagePerformance.stream()
656
.sorted((a, b) -> Integer.compare(b.getVisitPv(), a.getVisitPv()))
657
.limit(20)
658
.collect(Collectors.toList()));
659
report.setUserDemographics(demographics);
660
661
// Generate insights and recommendations
662
report.setInsights(generateInsights(report));
663
664
reportNotificationService.sendWeeklyReport(report);
665
666
} catch (WxErrorException e) {
667
logger.error("Failed to generate weekly report: {}", e.getMessage());
668
}
669
}
670
}
671
```
672
673
### Performance Monitoring
674
675
```java
676
@Component
677
public class PerformanceMonitor {
678
679
@EventListener
680
@Async
681
public void onAnalyticsRequest(AnalyticsRequestEvent event) {
682
long startTime = System.currentTimeMillis();
683
684
try {
685
// Monitor API response times
686
Object result = event.getAnalyticsCall().call();
687
688
long duration = System.currentTimeMillis() - startTime;
689
690
// Log performance metrics
691
logger.info("Analytics API call completed: {} ms for {}",
692
duration, event.getApiMethod());
693
694
// Alert if slow
695
if (duration > 5000) {
696
alertService.sendSlowApiAlert(event.getApiMethod(), duration);
697
}
698
699
} catch (Exception e) {
700
logger.error("Analytics API call failed: {}", e.getMessage());
701
alertService.sendApiFailureAlert(event.getApiMethod(), e);
702
}
703
}
704
}
705
```
706
707
The analytics service provides comprehensive insights into mini program performance with detailed metrics, trend analysis, user behavior patterns, and automated reporting capabilities.