Skip to content

Commit

Permalink
[Qwant] [MOBILE-604] - PiwikPro
Browse files Browse the repository at this point in the history
  • Loading branch information
jeromeboursier committed Dec 6, 2023
1 parent f09dd25 commit f356d33
Show file tree
Hide file tree
Showing 21 changed files with 248 additions and 4 deletions.
25 changes: 25 additions & 0 deletions Client.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,8 @@
6816BFC82A838DB500D334DA /* QwantIntroViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6816BFC42A838DB500D334DA /* QwantIntroViewController.swift */; };
6816BFC92A838DB500D334DA /* QwantIntroScreenWelcomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6816BFC52A838DB500D334DA /* QwantIntroScreenWelcomeView.swift */; };
6816BFCB2A838DB500D334DA /* Intro.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6816BFC72A838DB500D334DA /* Intro.xcassets */; };
681D75FF2AD945D700E63842 /* PiwikPROSDK in Frameworks */ = {isa = PBXBuildFile; productRef = 681D75FE2AD945D700E63842 /* PiwikPROSDK */; };
681D76012AD94E2A00E63842 /* QwantTracking.swift in Sources */ = {isa = PBXBuildFile; fileRef = 681D76002AD94E2A00E63842 /* QwantTracking.swift */; };
6821F06F29AE0DF700055321 /* UIResponder+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 966B0DC72926F60500A85A7E /* UIResponder+Extensions.swift */; };
682406C72A57FBD900466D27 /* ZapButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 682406C62A57FBD900466D27 /* ZapButton.swift */; };
682A6E4129CB491A009297F0 /* QwantZap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 682A6E4029CB491A009297F0 /* QwantZap.swift */; };
Expand Down Expand Up @@ -538,6 +540,7 @@
68AED22327EDB95D00C7A0AB /* QwantTPMenuVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68AED22227EDB95D00C7A0AB /* QwantTPMenuVC.swift */; };
68AED22527EDB96D00C7A0AB /* QwantTPMenuVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68AED22427EDB96D00C7A0AB /* QwantTPMenuVM.swift */; };
68BEB92A2A2A24D500009415 /* QwantSearchTableViewHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68BEB9292A2A24D500009415 /* QwantSearchTableViewHeader.swift */; };
68C2308B2AE121690005E01F /* SendQwantTrackingSetting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68C2308A2AE121690005E01F /* SendQwantTrackingSetting.swift */; };
68CAD4702A851672000571D9 /* ZapSetting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68CAD46F2A851672000571D9 /* ZapSetting.swift */; };
68CADF0128C7318100BCD1AB /* QwantSearchEnginesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68CADF0028C7318100BCD1AB /* QwantSearchEnginesTests.swift */; };
68CADF0328C7336A00BCD1AB /* QwantSearchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68CADF0228C7336A00BCD1AB /* QwantSearchTests.swift */; };
Expand Down Expand Up @@ -2500,6 +2503,7 @@
6816BFC42A838DB500D334DA /* QwantIntroViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QwantIntroViewController.swift; sourceTree = "<group>"; };
6816BFC52A838DB500D334DA /* QwantIntroScreenWelcomeView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QwantIntroScreenWelcomeView.swift; sourceTree = "<group>"; };
6816BFC72A838DB500D334DA /* Intro.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Intro.xcassets; sourceTree = "<group>"; };
681D76002AD94E2A00E63842 /* QwantTracking.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QwantTracking.swift; sourceTree = "<group>"; };
682406C62A57FBD900466D27 /* ZapButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZapButton.swift; sourceTree = "<group>"; };
682A6E4029CB491A009297F0 /* QwantZap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QwantZap.swift; sourceTree = "<group>"; };
682F7E1F2829452D00A04D13 /* QwantContentBlockerStatsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QwantContentBlockerStatsTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2547,6 +2551,7 @@
68AED22427EDB96D00C7A0AB /* QwantTPMenuVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QwantTPMenuVM.swift; sourceTree = "<group>"; };
68B44DA18DC0230AEB96C03D /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/LoginManager.strings; sourceTree = "<group>"; };
68BEB9292A2A24D500009415 /* QwantSearchTableViewHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QwantSearchTableViewHeader.swift; sourceTree = "<group>"; };
68C2308A2AE121690005E01F /* SendQwantTrackingSetting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendQwantTrackingSetting.swift; sourceTree = "<group>"; };
68CAD46F2A851672000571D9 /* ZapSetting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZapSetting.swift; sourceTree = "<group>"; };
68CADF0028C7318100BCD1AB /* QwantSearchEnginesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QwantSearchEnginesTests.swift; sourceTree = "<group>"; };
68CADF0228C7336A00BCD1AB /* QwantSearchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QwantSearchTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3695,6 +3700,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
681D75FF2AD945D700E63842 /* PiwikPROSDK in Frameworks */,
5A70EF0E295DFCCF00790249 /* Common in Frameworks */,
8A08EC6427EBDCAD00E119C7 /* AdServices.framework in Frameworks */,
8A08EC6227EBDCA400E119C7 /* iAd.framework in Frameworks */,
Expand Down Expand Up @@ -4952,6 +4958,7 @@
8A19ACB52A3290F9001C2147 /* NotificationsSetting.swift */,
8A19ACB72A329128001C2147 /* PrivacyPolicySetting.swift */,
8A093D822A4B68940099ABA5 /* PrivacySettingsDelegate.swift */,
68C2308A2AE121690005E01F /* SendQwantTrackingSetting.swift */,
);
path = Privacy;
sourceTree = "<group>";
Expand Down Expand Up @@ -7411,6 +7418,7 @@
E1FE133229C22782002A65FF /* BackgroundNotificationSurfaceUtility.swift */,
5A3A2A0C287F742C00B79EAC /* BackgroundSyncUtility.swift */,
602B3D6629B0E1DB0066DEF8 /* ConversionValueUtil.swift */,
681D76002AD94E2A00E63842 /* QwantTracking.swift */,
);
path = Application;
sourceTree = "<group>";
Expand Down Expand Up @@ -7973,6 +7981,7 @@
5A06135929D6052E008F3D38 /* TabDataStore */,
216A0D752A40E7AB008077BA /* Redux */,
8AF2D0FB2A5F272A00C7DD69 /* ComponentLibrary */,
681D75FE2AD945D700E63842 /* PiwikPROSDK */,
);
productName = Client;
productReference = F84B21BE1A090F8100AAB793 /* Client.app */;
Expand Down Expand Up @@ -8198,6 +8207,7 @@
43AFC0E027967BFA0039DDF4 /* XCRemoteSwiftPackageReference "Fuzi" */,
43C6A47D27A0679300C79856 /* XCRemoteSwiftPackageReference "MappaMundi" */,
5A37861729A2C337006B3A34 /* XCRemoteSwiftPackageReference "sentry-cocoa" */,
681D75FD2AD945D700E63842 /* XCRemoteSwiftPackageReference "piwik-pro-sdk-framework-ios" */,
);
productRefGroup = F84B21BF1A090F8100AAB793 /* Products */;
projectDirPath = "";
Expand Down Expand Up @@ -9515,6 +9525,7 @@
C8E2E80E23D20FD2005AACE6 /* FxAWebViewController.swift in Sources */,
E14F7DF2288F3F9F00E3722C /* ThemedTableSectionHeaderFooterView.swift in Sources */,
8A3EF7F22A2FCF4000796E3A /* DeleteExportedDataSetting.swift in Sources */,
68C2308B2AE121690005E01F /* SendQwantTrackingSetting.swift in Sources */,
8ADC2A142A33762900543DAA /* ReferringPage.swift in Sources */,
E1442FBF294782B6003680B0 /* CGRect+Extension.swift in Sources */,
96F8DA49280452CA00E53239 /* GleanPlumbContextProvider.swift in Sources */,
Expand Down Expand Up @@ -9643,6 +9654,7 @@
AB03032B2AB47AF300DCD8EF /* FakespotOptInCardView.swift in Sources */,
0BA02DB22942605600C92603 /* CreditCardHelper.swift in Sources */,
8A19ACB82A329128001C2147 /* PrivacyPolicySetting.swift in Sources */,
681D76012AD94E2A00E63842 /* QwantTracking.swift in Sources */,
E68AEDB01B18F81A00133D99 /* SwipeAnimator.swift in Sources */,
1DDE3DB32AC34E1E0039363B /* TabCell.swift in Sources */,
68AED22527EDB96D00C7A0AB /* QwantTPMenuVM.swift in Sources */,
Expand Down Expand Up @@ -12801,6 +12813,14 @@
version = 8.13.1;
};
};
681D75FD2AD945D700E63842 /* XCRemoteSwiftPackageReference "piwik-pro-sdk-framework-ios" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/PiwikPRO/piwik-pro-sdk-framework-ios";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 1.2.1;
};
};
/* End XCRemoteSwiftPackageReference section */

/* Begin XCSwiftPackageProductDependency section */
Expand Down Expand Up @@ -12962,6 +12982,11 @@
package = 435C85EE2788F4D00072B526 /* XCRemoteSwiftPackageReference "glean-swift" */;
productName = Glean;
};
681D75FE2AD945D700E63842 /* PiwikPROSDK */ = {
isa = XCSwiftPackageProductDependency;
package = 681D75FD2AD945D700E63842 /* XCRemoteSwiftPackageReference "piwik-pro-sdk-framework-ios" */;
productName = PiwikPROSDK;
};
781C19CE2A780BEC0000DF46 /* Common */ = {
isa = XCSwiftPackageProductDependency;
productName = Common;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,15 @@
"revision" : "f56a6e483163a761adc8cd25c337db0ed1eac524"
}
},
{
"identity" : "piwik-pro-sdk-framework-ios",
"kind" : "remoteSourceControl",
"location" : "https://github.com/PiwikPRO/piwik-pro-sdk-framework-ios",
"state" : {
"revision" : "61ced15d952b0b7e2fd182461d71b07510dc591c",
"version" : "1.2.1"
}
},
{
"identity" : "rust-components-swift",
"kind" : "remoteSourceControl",
Expand Down
1 change: 1 addition & 0 deletions Client/Application/AppLaunchUtil.swift
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ class AppLaunchUtil {

updateSessionCount()
adjustHelper.setupAdjust()
QwantTracking.setup()
}

private func setUserAgent() {
Expand Down
126 changes: 126 additions & 0 deletions Client/Application/QwantTracking.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/

import Common
import PiwikPROSDK

private typealias Event = (category: Category, action: Action, name: Name?)

enum QwantTrackingEvent {
case zap_toolbar(isIntention: Bool)
case zap_settings(isIntention: Bool)

case app_open

case tracking(isOn: Bool)

case closeTab(isPrivate: Bool)
case closeAllTabs(isIntention: Bool, isPrivate: Bool)

fileprivate var rawValue: Event {
switch self {
case .zap_toolbar(let isIntention):
return (.zap, .action(isIntention: isIntention), .toolbar)
case .zap_settings(let isIntention):
return (.zap, .action(isIntention: isIntention), .settings)
case .app_open:
return (.app, .open, nil)
case .tracking(let isOn):
return (.tracking, .toggle(isOn: isOn), nil)
case .closeTab(let isPrivate):
return (.tab, .action(isIntention: false), .closeOne(isPrivate: isPrivate))
case .closeAllTabs(let isIntention, let isPrivate):
return (.tab, .action(isIntention: isIntention), .closeAll(isPrivate: isPrivate))
}
}

func canSend() -> Bool {
switch self {
case .closeTab(let isPrivate): return isPrivate
case .closeAllTabs(let _, let isPrivate): return isPrivate
default: return true
}
}
}

private enum Category {
case zap
case app
case tracking
case tab

var rawValue: String {
switch self {
case .zap: return "Zap"
case .app: return "App"
case .tracking: return "Tracking"
case .tab: return "Tab"
}
}
}

private enum Action {
case action(isIntention: Bool)
case open
case toggle(isOn: Bool)

var rawValue: String {
switch self {
case .action(let isIntention): return isIntention ? "Intention" : "Confirmation"
case .toggle(let isOn): return isOn ? "On" : "Off"
case .open: return "Open"
}
}
}

private enum Name {
case toolbar
case settings
case closeAll(isPrivate: Bool)
case closeOne(isPrivate: Bool)

var rawValue: String {
switch self {
case .toolbar: return "Toolbar"
case .settings: return "Settings"
case .closeAll(let isPrivate): return "Close all - \(isPrivate ? "Private" : "Standard")"
case .closeOne(let isPrivate): return "Close one - \(isPrivate ? "Private" : "Standard")"
}
}
}

struct QwantTracking {
static func setup() {
#if DEBUG
PiwikTracker.sharedInstance(siteID: "9d3ebf38-ba38-4d72-9847-d412b59ebcd6",
baseURL: URL(string: "https://qwant-prod.piwik.pro")!)
#else
PiwikTracker.sharedInstance(siteID: "8904633f-a958-45ca-b540-df5248159519",
baseURL: URL(string: "https://qwant-prod.piwik.pro")!)
#endif
PiwikTracker.sharedInstance()?.sendApplicationDownload()
track(.app_open)
}

static func setEnabled(_ value: Bool) {
track(.tracking(isOn: value))
PiwikTracker.sharedInstance()?.dispatch()
PiwikTracker.sharedInstance()?.optOut = !value && !DeviceInfo.isSimulator()
let tabManager: TabManager = AppContainer.shared.resolve()
for tab in tabManager.tabs {
tab.webView?.setQwantCookies(tracking: value)
}
}

static func track(_ event: QwantTrackingEvent) {
guard event.canSend() else { return }
let event = event.rawValue
print("[QWANT] Tracking \([event.category.rawValue, event.action.rawValue, event.name?.rawValue].compactMap { $0 }.joined(separator: " - "))")
PiwikTracker.sharedInstance()?.sendEvent(category: event.category.rawValue,
action: event.action.rawValue,
name: event.name?.rawValue,
value: nil,
path: nil)
}
}
2 changes: 1 addition & 1 deletion Client/Frontend/Browser/BrowserViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2070,7 +2070,7 @@ extension BrowserViewController: LegacyTabDelegate {
KVOs.forEach { webView.addObserver(self, forKeyPath: $0.rawValue, options: .new, context: nil) }
webView.scrollView.addObserver(self.scrollController, forKeyPath: KVOConstants.contentSize.rawValue, options: .new, context: nil)
webView.uiDelegate = self
webView.setQwantCookies()
webView.setQwantCookies(tracking: profile.prefs.boolForKey(AppConstants.prefQwantTracking) ?? true)

let formPostHelper = FormPostHelper(tab: tab)
tab.addContentScript(formPostHelper, name: FormPostHelper.name())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Foundation
extension BrowserViewController {

func presentZapConfirmationAlert(_ sender: Any) {
QwantTracking.track(.zap_toolbar(isIntention: true))
let alert = UIAlertController(title: .QwantZap.ZapAlertTitle, message: nil, preferredStyle: .actionSheet)
alert.addAction(UIAlertAction(title: .QwantZap.ZapAlertOK, style: .destructive, handler: { [weak self] _ in
self?.doZap()
Expand All @@ -20,6 +21,7 @@ extension BrowserViewController {
}

func doZap() {
QwantTracking.track(.zap_toolbar(isIntention: false))
let viewController = ZapAnimationController(zap: self.zap)
viewController.onFinish = { [weak viewController] in
viewController?.willMove(toParent: nil)
Expand Down
2 changes: 2 additions & 0 deletions Client/Frontend/Browser/TabTrayController+KeyCommands.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,14 @@ extension LegacyGridTabViewController {
if let tab = tabManager.selectedTab {
tabManager.removeTab(tab)
}
QwantTracking.track(.closeTab(isPrivate: tabDisplayManager.isPrivate))
}

@objc
func didCloseAllTabsKeyCommand() {
TelemetryWrapper.recordEvent(category: .action, method: .press, object: .keyCommand, extras: ["action": "close-all-tabs"])
closeTabsTrayBackground()
QwantTracking.track(.closeAllTabs(isIntention: false, isPrivate: tabDisplayManager.isPrivate))
}

@objc
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,7 @@ extension LegacyGridTabViewController: LegacyTabCellDelegate {
let tab = tabDisplayManager.dataStore.at(indexPath.item) {
closeTabAction(tab: tab, cell: cell)
}
QwantTracking.track(.closeTab(isPrivate: tabDisplayManager.isPrivate))
}
}

Expand Down Expand Up @@ -699,7 +700,10 @@ extension LegacyGridTabViewController {
let controller = AlertController(title: nil, message: nil, preferredStyle: .actionSheet)
controller.addAction(UIAlertAction(title: .AppMenu.AppMenuCloseAllTabsTitleString,
style: .destructive,
handler: { _ in self.closeTabsTrayBackground() }),
handler: { _ in
QwantTracking.track(.closeAllTabs(isIntention: false, isPrivate: self.tabDisplayManager.isPrivate))
self.closeTabsTrayBackground()
}),
accessibilityIdentifier: AccessibilityIdentifiers.TabTray.deleteCloseAllButton)
controller.addAction(UIAlertAction(title: .TabTrayCloseAllTabsPromptCancel,
style: .cancel,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,7 @@ extension LegacyTabTrayViewController {
@objc
func didTapDeleteTabs(_ sender: UIBarButtonItem) {
viewModel.didTapDeleteTab(sender)
QwantTracking.track(.closeAllTabs(isIntention: true, isPrivate: viewModel.segmentToFocus == .privateTabs))
}

@objc
Expand Down
1 change: 1 addition & 0 deletions Client/Frontend/Browser/TopTabsViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ extension TopTabsViewController: TopTabCellDelegate {
func tabCellDidClose(_ cell: UICollectionViewCell) {
topTabDisplayManager.closeActionPerformed(forCell: cell)
NotificationCenter.default.post(name: .TopTabsTabClosed, object: nil)
QwantTracking.track(.closeTab(isPrivate: topTabDisplayManager.isPrivate))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,11 @@ class AppSettingsTableViewController: SettingsTableViewController,
settingsDelegate: parentCoordinator))

privacySettings += [
PrivacyPolicySetting(theme: themeManager.currentTheme, settingsDelegate: parentCoordinator)
PrivacyPolicySetting(theme: themeManager.currentTheme, settingsDelegate: parentCoordinator),
SendQwantTrackingSetting(prefs: profile.prefs,
delegate: settingsDelegate,
theme: themeManager.currentTheme,
settingsDelegate: parentCoordinator)
]

return [SettingSection(title: NSAttributedString(string: .AppSettingsPrivacyTitle),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/

import Common
import Foundation
import Shared

class SendQwantTrackingSetting: BoolSetting {
private weak var settingsDelegate: SupportSettingsDelegate?

init(prefs: Prefs,
delegate: SettingsDelegate?,
theme: Theme,
settingsDelegate: SupportSettingsDelegate?) {

self.settingsDelegate = settingsDelegate
super.init(
prefs: prefs,
prefKey: AppConstants.prefQwantTracking,
defaultValue: true,
attributedTitleText: NSAttributedString(string: .QwantTracking.SettingsTitle),
attributedStatusText: NSAttributedString(string: .QwantTracking.SettingsSubtitle),
settingDidChange: {
QwantTracking.setEnabled($0)
}
)
}
}
Loading

0 comments on commit f356d33

Please sign in to comment.