Fjalapeno has submitted this change and it was merged.
Change subject: Implement search analytics - T90257
......................................................................
Implement search analytics - T90257
Change-Id: I4af344ff1f4511f8cb4f388a55dc3dfde4db025a
---
M Wikipedia.xcodeproj/project.pbxproj
M Wikipedia/EventLogging/EventLoggingFunnel.h
M Wikipedia/View Controllers/Navigation/Top/TopMenuViewController.m
M Wikipedia/View Controllers/SearchResults/SearchResultsController.h
M Wikipedia/View Controllers/SearchResults/SearchResultsController.m
M Wikipedia/View
Controllers/WebView/Footer/SubFooters/ReadMore/WMFReadMoreViewController.xib
A Wikipedia/WMFSearchFunnel.h
A Wikipedia/WMFSearchFunnel.m
8 files changed, 181 insertions(+), 12 deletions(-)
Approvals:
Bgerstle: Looks good to me, approved
jenkins-bot: Verified
diff --git a/Wikipedia.xcodeproj/project.pbxproj
b/Wikipedia.xcodeproj/project.pbxproj
index eaa3407..22ad468 100644
--- a/Wikipedia.xcodeproj/project.pbxproj
+++ b/Wikipedia.xcodeproj/project.pbxproj
@@ -191,6 +191,7 @@
0EBC56961AD5B22800E82CDD /*
BITHockeyManagerWMFExtensionsTests.m in Sources */ = {isa = PBXBuildFile;
fileRef = 0EBC56951AD5B22800E82CDD /* BITHockeyManagerWMFExtensionsTests.m */;
};
0EBC56971AD5B69300E82CDD /* BITHockeyManager+WMFExtensions.m in
Sources */ = {isa = PBXBuildFile; fileRef = 0EBC567E1AD442CC00E82CDD /*
BITHockeyManager+WMFExtensions.m */; };
0EE7687B1AF982C100A5D046 /* WMFArticleProtocol.m in Sources */
= {isa = PBXBuildFile; fileRef = 0EE7687A1AF982C100A5D046 /*
WMFArticleProtocol.m */; };
+ 0EE768811AFD25CC00A5D046 /* WMFSearchFunnel.m in Sources */ =
{isa = PBXBuildFile; fileRef = 0EE768801AFD25CC00A5D046 /* WMFSearchFunnel.m
*/; };
701FF5EE601DEA3FCAB7EFD3 /* libPods.a in Frameworks */ = {isa =
PBXBuildFile; fileRef = D82982ED992F47428037BDF2 /* libPods.a */; };
954BA118838BF8BA6B01C34A /* libPods-WikipediaUnitTests.a in
Frameworks */ = {isa = PBXBuildFile; fileRef = 8CE61C6963F825760822A28A /*
libPods-WikipediaUnitTests.a */; };
BC0FED621AAA0263002488D7 /* WMFCodingStyle.m in Sources */ =
{isa = PBXBuildFile; fileRef = BC6FEAE01A9B7EFD00A1D890 /* WMFCodingStyle.m */;
};
@@ -727,6 +728,8 @@
0EBC56951AD5B22800E82CDD /*
BITHockeyManagerWMFExtensionsTests.m */ = {isa = PBXFileReference; fileEncoding
= 4; lastKnownFileType = sourcecode.c.objc; path =
BITHockeyManagerWMFExtensionsTests.m; sourceTree = "<group>"; };
0EE768791AF982C100A5D046 /* WMFArticleProtocol.h */ = {isa =
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name =
WMFArticleProtocol.h; path = Wikipedia/Protocols/WMFArticleProtocol.h;
sourceTree = SOURCE_ROOT; };
0EE7687A1AF982C100A5D046 /* WMFArticleProtocol.m */ = {isa =
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name
= WMFArticleProtocol.m; path = Wikipedia/Protocols/WMFArticleProtocol.m;
sourceTree = SOURCE_ROOT; };
+ 0EE7687F1AFD25CC00A5D046 /* WMFSearchFunnel.h */ = {isa =
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path =
WMFSearchFunnel.h; sourceTree = "<group>"; };
+ 0EE768801AFD25CC00A5D046 /* WMFSearchFunnel.m */ = {isa =
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path
= WMFSearchFunnel.m; sourceTree = "<group>"; };
17A2F22335C5256576CEDBDD /*
Pods-WikipediaUnitTests.release.xcconfig */ = {isa = PBXFileReference;
includeInIndex = 1; lastKnownFileType = text.xcconfig; name =
"Pods-WikipediaUnitTests.release.xcconfig"; path = "Pods/Target Support
Files/Pods-WikipediaUnitTests/Pods-WikipediaUnitTests.release.xcconfig";
sourceTree = "<group>"; };
1BC5FB470144D2C10C55A037 /*
Pods-WikipediaUnitTests.alpha.xcconfig */ = {isa = PBXFileReference;
includeInIndex = 1; lastKnownFileType = text.xcconfig; name =
"Pods-WikipediaUnitTests.alpha.xcconfig"; path = "Pods/Target Support
Files/Pods-WikipediaUnitTests/Pods-WikipediaUnitTests.alpha.xcconfig";
sourceTree = "<group>"; };
357504E50DA104E39C6ACFEB /* Pods.release.xcconfig */ = {isa =
PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name =
Pods.release.xcconfig; path = "Pods/Target Support
Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; };
@@ -2472,6 +2475,8 @@
D47BF5D3197870390067C3BC /* SavedPagesFunnel.m
*/,
C913C89A1A94019A00BEEAF0 /*
WMFSuggestedPagesFunnel.h */,
C913C89B1A94019A00BEEAF0 /*
WMFSuggestedPagesFunnel.m */,
+ 0EE7687F1AFD25CC00A5D046 /* WMFSearchFunnel.h
*/,
+ 0EE768801AFD25CC00A5D046 /* WMFSearchFunnel.m
*/,
);
name = EventLogging;
sourceTree = "<group>";
@@ -3087,6 +3092,7 @@
0452C803195CB216007925A6 /*
UIViewController+ModalsSearch.m in Sources */,
04CCA0C319830A44000E982A /* ReferenceVC.m in
Sources */,
BCB669B71A83F6C400C7B1FE /* MWKSectionList.m in
Sources */,
+ 0EE768811AFD25CC00A5D046 /* WMFSearchFunnel.m
in Sources */,
BCB66A0C1A85183000C7B1FE /*
NSString+WMFHTMLParsing.m in Sources */,
04733A041AC6123400E365E5 /*
WMFLoadingIndicatorOverlay.m in Sources */,
BCB669AF1A83F6C400C7B1FE /* MWKHistoryList.m in
Sources */,
diff --git a/Wikipedia/EventLogging/EventLoggingFunnel.h
b/Wikipedia/EventLogging/EventLoggingFunnel.h
index fb4407d..2bbba9c 100644
--- a/Wikipedia/EventLogging/EventLoggingFunnel.h
+++ b/Wikipedia/EventLogging/EventLoggingFunnel.h
@@ -28,8 +28,8 @@
*/
@interface EventLoggingFunnel : NSObject
-@property NSString* schema;
-@property int revision;
+@property (nonatomic, strong) NSString* schema;
+@property (nonatomic, assign) int revision;
/**
* This constructor should be called internally by derived classes
diff --git a/Wikipedia/View Controllers/Navigation/Top/TopMenuViewController.m
b/Wikipedia/View Controllers/Navigation/Top/TopMenuViewController.m
index e4f55b0..a77391f 100644
--- a/Wikipedia/View Controllers/Navigation/Top/TopMenuViewController.m
+++ b/Wikipedia/View Controllers/Navigation/Top/TopMenuViewController.m
@@ -30,6 +30,7 @@
#import "AccountCreationViewController.h"
#import "WMF_Colors.h"
#import "UIView+ConstraintsScale.h"
+#import "WMFSearchFunnel.h"
@interface TopMenuViewController (){
}
@@ -57,6 +58,11 @@
@property (strong, nonatomic) NSDictionary* navBarSubViews;
@property (strong, nonatomic) NSDictionary* navBarSubViewMetrics;
+
+@property (strong, nonatomic) WMFSearchFunnel* searchFunnel;
+
+
+
@end
@implementation TopMenuViewController
@@ -72,7 +78,9 @@
[super viewDidLoad];
// Do any additional setup after loading the view.
- self.searchResultsController = [SearchResultsController
standardSearchResultsController];
+ self.searchFunnel = [[WMFSearchFunnel alloc] init];
+ self.searchResultsController = [SearchResultsController
standardSearchResultsController];
+ self.searchResultsController.searchFunnel = self.searchFunnel;
[self setupNavbarContainerSubviews];
@@ -562,6 +570,7 @@
case NAVBAR_MODE_DEFAULT:
case NAVBAR_MODE_DEFAULT_WITH_TOC:
self.navBarMode = NAVBAR_MODE_SEARCH;
+ [self.searchFunnel logSearchStart];
break;
default:
break;
@@ -575,6 +584,8 @@
self.navBarMode = NAVBAR_MODE_DEFAULT;
[self updateTOCButtonVisibility];
[self hideSearchResultsController];
+ [self.searchFunnel logSearchCancel];
+
break;
default:
break;
diff --git a/Wikipedia/View Controllers/SearchResults/SearchResultsController.h
b/Wikipedia/View Controllers/SearchResults/SearchResultsController.h
index 1fc827d..3a25a88 100644
--- a/Wikipedia/View Controllers/SearchResults/SearchResultsController.h
+++ b/Wikipedia/View Controllers/SearchResults/SearchResultsController.h
@@ -2,6 +2,7 @@
#import <UIKit/UIKit.h>
@class WMFIntrinsicContentSizeAwareTableView;
+@class WMFSearchFunnel;
@interface SearchResultsController : UIViewController <UITableViewDelegate,
UITableViewDataSource>
@@ -11,6 +12,11 @@
@property (strong, nonatomic) NSString* searchString;
/**
+ * Set the funnel for tracking search results
+ */
+@property (strong, nonatomic) WMFSearchFunnel* searchFunnel;
+
+/**
* Specify articles that should not be displayed in the search results
*/
@property (strong, nonatomic) NSArray* articlesToExcludeFromResults;
diff --git a/Wikipedia/View Controllers/SearchResults/SearchResultsController.m
b/Wikipedia/View Controllers/SearchResults/SearchResultsController.m
index 4d53c75..ccdddf6 100644
--- a/Wikipedia/View Controllers/SearchResults/SearchResultsController.m
+++ b/Wikipedia/View Controllers/SearchResults/SearchResultsController.m
@@ -25,6 +25,7 @@
#import <BlocksKit/BlocksKit.h>
#import "WMFIntrinsicContentSizeAwareTableView.h"
#import "UIScrollView+WMFScrollsToTop.h"
+#import "WMFSearchFunnel.h"
static NSString* const kWMFSearchCellID = @"SearchResultCell";
static CGFloat const kWMFSearchDelay = 0.4;
@@ -46,10 +47,10 @@
@property (nonatomic, assign) WMFSearchResultsControllerType type;
-@property (assign, nonatomic) NSUInteger maxResults;
-@property (assign, nonatomic) NSUInteger minResultsBeforeRunningFullTextSearch;
+@property (nonatomic, assign) NSUInteger maxResults;
+@property (nonatomic, assign) NSUInteger minResultsBeforeRunningFullTextSearch;
-@property (assign, nonatomic) BOOL highlightSearchTermInResultTitles;
+@property (nonatomic, assign) BOOL highlightSearchTermInResultTitles;
@property (nonatomic, strong) NSString* searchSuggestion;
@@ -67,11 +68,13 @@
@property (nonatomic, weak) IBOutlet SearchDidYouMeanButton* didYouMeanButton;
@property (nonatomic, weak) IBOutlet SearchMessageLabel* searchMessageLabel;
-@property (strong, nonatomic) RecentSearchesViewController*
recentSearchesViewController;
+@property (nonatomic, strong) RecentSearchesViewController*
recentSearchesViewController;
@property (nonatomic, weak) IBOutlet UIView* recentSearchesContainer;
-@property (strong, nonatomic) SearchResultCell* offScreenSizingCell;
+@property (nonatomic, strong) SearchResultCell* offScreenSizingCell;
+
+@property (nonatomic, strong) NSDate* searchStartTime;
@end
@@ -200,6 +203,7 @@
textFieldContainer.textField.text = self.searchSuggestion;
self.searchString = self.searchSuggestion;
[self searchAfterDelay:@0.0f reason:SEARCH_REASON_DID_YOU_MEAN_TAPPED];
+ [self.searchFunnel logSearchDidYouMean];
}
- (void)observeValueForKeyPath:(NSString*)keyPath
@@ -228,6 +232,14 @@
}
}
+- (void)setSearchStartTime {
+ self.searchStartTime = [NSDate new];
+}
+
+- (NSTimeInterval)searchTime {
+ return [[NSDate new] timeIntervalSinceDate:self.searchStartTime];
+}
+
- (void)cancelDelayedSearch {
if (self.delayedSearchTimer) {
[self.delayedSearchTimer invalidate];
@@ -239,6 +251,7 @@
if (self.searchString.length == 0) {
[self clearSearchResults];
} else {
+ [self setSearchStartTime];
[self searchAfterDelay:@(kWMFSearchDelay)
reason:SEARCH_REASON_SEARCH_STRING_CHANGED];
}
}
@@ -405,8 +418,10 @@
self.searchResults =
[[self.searchResults
arrayByAddingObjectsFromArray:supplementalFullTextResults]
wmf_arrayByTrimmingToLength:self.maxResults];
+ [self.searchFunnel
logSearchResultsWithTypeOfSearch:WMFSearchTypeFull
resultCount:[self.searchResults count] elapsedTime:[self searchTime]];
} else {
self.searchResults = [searchResults
wmf_arrayByTrimmingToLength:self.maxResults];
+ [self.searchFunnel
logSearchResultsWithTypeOfSearch:WMFSearchTypePrefix
resultCount:[self.searchResults count] elapsedTime:[self searchTime]];
}
//NSLog(@"self.searchResultsOrdered = %@",
self.searchResultsOrdered);
@@ -420,6 +435,7 @@
// do a full-text search too, the results of which will be
appended to the prefix results.
// Note: this also has to be done in the
FETCH_FINAL_STATUS_FAILED case below.
if ((self.searchResults.count <
self.minResultsBeforeRunningFullTextSearch) && (searchResultFetcher.searchType
== SEARCH_TYPE_TITLES)) {
+ [self.searchFunnel logSearchAutoSwitch];
[self
performSupplementalFullTextSearchForTerm:searchResultFetcher.searchTerm];
}
}
@@ -450,8 +466,12 @@
[self.searchMessageLabel
showWithText:error.localizedDescription];
}
- //[self.searchMessageLabel
showWithText:error.localizedDescription];
- //[self showAlert:error.localizedDescription
type:ALERT_TYPE_MIDDLE duration:-1];
+ if (searchResultFetcher.searchReason ==
SEARCH_REASON_SUPPLEMENT_PREFIX_WITH_FULL_TEXT) {
+ [self.searchFunnel
logShowSearchErrorWithTypeOfSearch:WMFSearchTypeFull elapsedTime:[[NSDate new]
timeIntervalSinceDate:self.searchStartTime]];
+ } else {
+ [self.searchFunnel
logShowSearchErrorWithTypeOfSearch:WMFSearchTypePrefix elapsedTime:[[NSDate
new] timeIntervalSinceDate:self.searchStartTime]];
+ }
+
break;
}
@@ -623,6 +643,7 @@
NSString* title = result[@"title"];
[self loadArticleWithTitle:title];
+ [self.searchFunnel logSearchResultTap];
}
- (void)loadArticleWithTitle:(NSString*)title {
diff --git a/Wikipedia/View
Controllers/WebView/Footer/SubFooters/ReadMore/WMFReadMoreViewController.xib
b/Wikipedia/View
Controllers/WebView/Footer/SubFooters/ReadMore/WMFReadMoreViewController.xib
index 3a713b8..e1c13e5 100644
--- a/Wikipedia/View
Controllers/WebView/Footer/SubFooters/ReadMore/WMFReadMoreViewController.xib
+++ b/Wikipedia/View
Controllers/WebView/Footer/SubFooters/ReadMore/WMFReadMoreViewController.xib
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0"
toolsVersion="6254" systemVersion="14C109" targetRuntime="iOS.CocoaTouch"
propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0"
toolsVersion="7702" systemVersion="14D136" targetRuntime="iOS.CocoaTouch"
propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
<dependencies>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin"
version="6247"/>
+ <deployment identifier="iOS"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin"
version="7701"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1"
userLabel="File's Owner" customClass="WMFReadMoreViewController">
diff --git a/Wikipedia/WMFSearchFunnel.h b/Wikipedia/WMFSearchFunnel.h
new file mode 100644
index 0000000..4eded86
--- /dev/null
+++ b/Wikipedia/WMFSearchFunnel.h
@@ -0,0 +1,30 @@
+//
+// WMFSearchFunnel.h
+// Wikipedia
+//
+// Created by Corey Floyd on 5/8/15.
+// Copyright (c) 2015 Wikimedia Foundation. All rights reserved.
+//
+
+#import "EventLoggingFunnel.h"
+
+typedef NS_ENUM (NSUInteger, WMFSearchType) {
+ WMFSearchTypePrefix = 0,
+ WMFSearchTypeFull
+};
+
+@interface WMFSearchFunnel : EventLoggingFunnel
+
+- (void)logSearchStart;
+- (void)logSearchAutoSwitch;
+- (void)logSearchDidYouMean;
+- (void)logSearchResultTap;
+- (void)logSearchCancel;
+
+- (void)logSearchResultsWithTypeOfSearch:(WMFSearchType)type
resultCount:(NSUInteger)count elapsedTime:(NSTimeInterval)searchTime;
+
+- (void)logShowSearchErrorWithTypeOfSearch:(WMFSearchType)type
elapsedTime:(NSTimeInterval)searchTime;
+
+
+
+@end
diff --git a/Wikipedia/WMFSearchFunnel.m b/Wikipedia/WMFSearchFunnel.m
new file mode 100644
index 0000000..da544df
--- /dev/null
+++ b/Wikipedia/WMFSearchFunnel.m
@@ -0,0 +1,94 @@
+//
+// WMFSearchFunnel.m
+// Wikipedia
+//
+// Created by Corey Floyd on 5/8/15.
+// Copyright (c) 2015 Wikimedia Foundation. All rights reserved.
+//
+
+#import "WMFSearchFunnel.h"
+
+static NSString* const kSchemaName = @"MobileWikiAppSearch";
+static int const kSchemaVersion = 10641988;
+static NSString* const kAppInstallIdKey = @"appInstallID";
+static NSString* const kSearchSessionTokenKey = @"searchSessionToken";
+
+static NSString* const kActionKey = @"action";
+static NSString* const kSearchTypeKey = @"typeOfSearch";
+static NSString* const kSearchTimeKey = @"timeToDisplayResults";
+static NSString* const kSearchResultsCount = @"numberOfResults";
+
+@interface WMFSearchFunnel ()
+
+@property (nonatomic, strong) NSString* appInstallId;
+@property (nonatomic, strong) NSString* searchSessionToken;
+
+@end
+
+@implementation WMFSearchFunnel
+
+- (instancetype)init {
+ self = [super initWithSchema:kSchemaName version:kSchemaVersion];
+ if (self) {
+ _appInstallId = [self persistentUUID:kSchemaName];
+ }
+ return self;
+}
+
+- (NSString*)searchSessionToken {
+ if (!_searchSessionToken) {
+ _searchSessionToken = [[NSUUID UUID] UUIDString];
+ }
+ return _searchSessionToken;
+}
+
+- (NSDictionary*)preprocessData:(NSDictionary*)eventData {
+ NSMutableDictionary* dict = [eventData mutableCopy];
+ dict[kAppInstallIdKey] = self.appInstallId;
+ dict[kSearchSessionTokenKey] = self.searchSessionToken;
+ return [dict copy];
+}
+
+- (void)logSearchStart {
+ self.searchSessionToken = nil;
+ [self log:@{kActionKey: @"start"}];
+}
+
+- (void)logSearchAutoSwitch {
+ [self log:@{kActionKey: @"autoswitch"}];
+}
+
+- (void)logSearchDidYouMean {
+ [self log:@{kActionKey: @"didyoumean"}];
+}
+
+- (void)logSearchResultTap {
+ [self log:@{kActionKey: @"click"}];
+}
+
+- (void)logSearchCancel {
+ [self log:@{kActionKey: @"cancel"}];
+}
+
+- (void)logSearchResultsWithTypeOfSearch:(WMFSearchType)type
resultCount:(NSUInteger)count elapsedTime:(NSTimeInterval)searchTime {
+ [self log:@{kActionKey: @"results",
+ kSearchTypeKey: [[self class] stringForSearchType:type],
+ kSearchResultsCount: @(count),
+ kSearchTimeKey: @((NSInteger)(searchTime * 1000))}];
+}
+
+- (void)logShowSearchErrorWithTypeOfSearch:(WMFSearchType)type
elapsedTime:(NSTimeInterval)searchTime {
+ [self log:@{kActionKey: @"error",
+ kSearchTypeKey: [[self class] stringForSearchType:type],
+ kSearchTimeKey: @((NSInteger)(searchTime * 1000))}];
+}
+
++ (NSString*)stringForSearchType:(WMFSearchType)type {
+ if (type == WMFSearchTypePrefix) {
+ return @"prefix";
+ }
+
+ return @"full";
+}
+
+@end
--
To view, visit https://gerrit.wikimedia.org/r/209792
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I4af344ff1f4511f8cb4f388a55dc3dfde4db025a
Gerrit-PatchSet: 3
Gerrit-Project: apps/ios/wikipedia
Gerrit-Branch: master
Gerrit-Owner: Fjalapeno <[email protected]>
Gerrit-Reviewer: Bgerstle <[email protected]>
Gerrit-Reviewer: Fjalapeno <[email protected]>
Gerrit-Reviewer: Mhurd <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits