diff --git a/Makefile b/Makefile index 40bb0d0b40..c5c1574ea7 100644 --- a/Makefile +++ b/Makefile @@ -45,8 +45,6 @@ deploy-appbundle: $(OUTPUT_DIR)/analytics-ga.js \ $(BUILD_DIR)/analytics-ga.min.js \ $(BUILD_DIR)/analytics-ga.min.map \ - $(BUILD_DIR)/analytics-amplitude.min.js \ - $(BUILD_DIR)/analytics-amplitude.min.map \ $(DEPLOY_DIR) deploy-lib-jitsi-meet: diff --git a/android/sdk/build.gradle b/android/sdk/build.gradle index 6203f46342..457c222dda 100644 --- a/android/sdk/build.gradle +++ b/android/sdk/build.gradle @@ -25,6 +25,7 @@ dependencies { implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}" implementation 'org.webkit:android-jsc:+' + implementation 'com.amplitude:android-sdk:2.14.1' implementation 'com.dropbox.core:dropbox-core-sdk:3.0.8' api 'com.facebook.react:react-native:+' diff --git a/android/sdk/src/main/java/org/jitsi/meet/sdk/ReactInstanceManagerHolder.java b/android/sdk/src/main/java/org/jitsi/meet/sdk/ReactInstanceManagerHolder.java index 9167932cab..79400910be 100644 --- a/android/sdk/src/main/java/org/jitsi/meet/sdk/ReactInstanceManagerHolder.java +++ b/android/sdk/src/main/java/org/jitsi/meet/sdk/ReactInstanceManagerHolder.java @@ -53,6 +53,7 @@ class ReactInstanceManagerHolder { new PictureInPictureModule(reactContext), new ProximityModule(reactContext), new WiFiStatsModule(reactContext), + new org.jitsi.meet.sdk.analytics.AmplitudeModule(reactContext), new org.jitsi.meet.sdk.dropbox.Dropbox(reactContext), new org.jitsi.meet.sdk.net.NAT64AddrInfoModule(reactContext))); diff --git a/android/sdk/src/main/java/org/jitsi/meet/sdk/analytics/AmplitudeModule.java b/android/sdk/src/main/java/org/jitsi/meet/sdk/analytics/AmplitudeModule.java new file mode 100644 index 0000000000..ee972b2e04 --- /dev/null +++ b/android/sdk/src/main/java/org/jitsi/meet/sdk/analytics/AmplitudeModule.java @@ -0,0 +1,87 @@ +/* + * Copyright @ 2019-present 8x8, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jitsi.meet.sdk.analytics; + +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.ReadableMap; + +import com.amplitude.api.Amplitude; + +import org.json.JSONException; +import org.json.JSONObject; + +/** + * Implements the react-native module for the Amplitude integration. + */ +public class AmplitudeModule + extends ReactContextBaseJavaModule { + + public AmplitudeModule(ReactApplicationContext reactContext) { + super(reactContext); + } + + /** + * Initializes the Amplitude SDK. + * + * @param instanceName The name of the Amplitude instance. Should + * be used only for multi-project logging. + * @param apiKey The API_KEY of the Amplitude project. + */ + @ReactMethod + public void init(String instanceName, String apiKey) { + Amplitude.getInstance(instanceName).initialize(getCurrentActivity(), apiKey); + } + + /** + * Sets the user properties for an Amplitude instance. + * + * @param instanceName The name of the Amplitude instance. + * @param userProps JSON string with user properties to be set. + */ + @ReactMethod + public void setUserProperties(String instanceName, ReadableMap userProps) { + if (userProps != null) { + Amplitude.getInstance(instanceName).setUserProperties( + new JSONObject(userProps.toHashMap())); + } + } + + /** + * Log an analytics event. + * + * @param instanceName The name of the Amplitude instance. + * @param eventType The event type. + * @param eventPropsString JSON string with the event properties. + */ + @ReactMethod + public void logEvent(String instanceName, String eventType, String eventPropsString) { + JSONObject eventProps = null; + try { + eventProps = new JSONObject(eventPropsString); + Amplitude.getInstance(instanceName).logEvent(eventType, eventProps); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + @Override + public String getName() { + return "Amplitude"; + } +} diff --git a/ios/Podfile b/ios/Podfile index f8f133caa7..e29364433f 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -35,6 +35,7 @@ target 'JitsiMeet' do pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec' + pod 'Amplitude-iOS', '~> 4.0.4' pod 'ObjectiveDropboxOfficial' pod 'react-native-background-timer', diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 85151f7fa5..5638627aa3 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1,4 +1,5 @@ PODS: + - Amplitude-iOS (4.0.4) - boost-for-react-native (1.63.0) - BVLinearGradient (2.5.3): - React @@ -154,6 +155,7 @@ PODS: - yoga (0.57.8.React) DEPENDENCIES: + - Amplitude-iOS (~> 4.0.4) - BVLinearGradient (from `../node_modules/react-native-linear-gradient`) - Crashlytics - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) @@ -185,6 +187,7 @@ DEPENDENCIES: SPEC REPOS: https://github.com/cocoapods/specs.git: + - Amplitude-iOS - boost-for-react-native - Crashlytics - Fabric @@ -235,6 +238,7 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/yoga" SPEC CHECKSUMS: + Amplitude-iOS: 2ad4d7270c99186236c1272a3a9425463b1ae1a7 boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c BVLinearGradient: 0d985ec461359c82bc254f26d11008bdae50d17a Crashlytics: 07fb167b1694128c1c9a5a5cc319b0e9c3ca0933 @@ -268,6 +272,6 @@ SPEC CHECKSUMS: SDWebImage: c5594f1a19c48d526d321e548902b56b479cd508 yoga: 74cdf036c30820443b25ade59916236b1e95ee93 -PODFILE CHECKSUM: 7d1909450626f31f9ea2de80122a66a50af2e1ea +PODFILE CHECKSUM: b300161e95d65c24b91368803afb8873f4b873cc -COCOAPODS: 1.6.0 +COCOAPODS: 1.6.1 diff --git a/ios/sdk/sdk.xcodeproj/project.pbxproj b/ios/sdk/sdk.xcodeproj/project.pbxproj index ed6d4cbfa8..93a79065b7 100644 --- a/ios/sdk/sdk.xcodeproj/project.pbxproj +++ b/ios/sdk/sdk.xcodeproj/project.pbxproj @@ -34,6 +34,7 @@ 75635B0B20751D6D00F29C9F /* left.wav in Resources */ = {isa = PBXBuildFile; fileRef = 75635B0920751D6D00F29C9F /* left.wav */; }; 87FE6F3321E52437004A5DC7 /* incomingMessage.wav in Resources */ = {isa = PBXBuildFile; fileRef = 87FE6F3221E52437004A5DC7 /* incomingMessage.wav */; }; A4414AE020B37F1A003546E6 /* rejected.wav in Resources */ = {isa = PBXBuildFile; fileRef = A4414ADF20B37F1A003546E6 /* rejected.wav */; }; + A480429C21EE335600289B73 /* AmplitudeModule.m in Sources */ = {isa = PBXBuildFile; fileRef = A480429B21EE335600289B73 /* AmplitudeModule.m */; }; A4A934E9212F3ADB001E9388 /* Dropbox.m in Sources */ = {isa = PBXBuildFile; fileRef = A4A934E8212F3ADB001E9388 /* Dropbox.m */; }; C6245F5D2053091D0040BE68 /* image-resize@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C6245F5B2053091D0040BE68 /* image-resize@2x.png */; }; C6245F5E2053091D0040BE68 /* image-resize@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = C6245F5C2053091D0040BE68 /* image-resize@3x.png */; }; @@ -80,6 +81,7 @@ 98E09B5C73D9036B4ED252FC /* Pods-JitsiMeet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet.debug.xcconfig"; path = "../Pods/Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet.debug.xcconfig"; sourceTree = ""; }; 9C77CA3CC919B081F1A52982 /* Pods-JitsiMeet.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet.release.xcconfig"; path = "../Pods/Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet.release.xcconfig"; sourceTree = ""; }; A4414ADF20B37F1A003546E6 /* rejected.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = rejected.wav; path = ../../sounds/rejected.wav; sourceTree = ""; }; + A480429B21EE335600289B73 /* AmplitudeModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AmplitudeModule.m; path = src/analytics/AmplitudeModule.m; sourceTree = SOURCE_ROOT; }; A4A934E8212F3ADB001E9388 /* Dropbox.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Dropbox.m; sourceTree = ""; }; A4A934EB21349A06001E9388 /* Dropbox.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Dropbox.h; sourceTree = ""; }; C6245F5B2053091D0040BE68 /* image-resize@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "image-resize@2x.png"; path = "src/picture-in-picture/image-resize@2x.png"; sourceTree = ""; }; @@ -148,6 +150,7 @@ 0BD906E71EC0C00300C8C18E /* src */ = { isa = PBXGroup; children = ( + A480429821ECE2D800289B73 /* analytics */, 0BB9AD7C1F60356D001C08DB /* AppInfo.m */, 0BCA495C1EC4B6C600B793EE /* AudioMode.m */, C69EFA02209A0EFD0027712B /* callkit */, @@ -183,6 +186,15 @@ name = Frameworks; sourceTree = ""; }; + A480429821ECE2D800289B73 /* analytics */ = { + isa = PBXGroup; + children = ( + A480429B21EE335600289B73 /* AmplitudeModule.m */, + ); + name = analytics; + path = "New Group"; + sourceTree = ""; + }; A4A934E7212F3AB8001E9388 /* dropbox */ = { isa = PBXGroup; children = ( @@ -374,6 +386,10 @@ ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet-resources.sh", + "${PODS_ROOT}/Amplitude-iOS/Amplitude/api.amplitude.com.der", + "${PODS_ROOT}/Amplitude-iOS/Amplitude/ComodoCaLimitedRsaCertificationAuthority.der", + "${PODS_ROOT}/Amplitude-iOS/Amplitude/ComodoRsaCA.der", + "${PODS_ROOT}/Amplitude-iOS/Amplitude/ComodoRsaDomainValidationCA.der", "${PODS_ROOT}/GoogleSignIn/Resources/GoogleSignIn.bundle", "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/AntDesign.ttf", "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Entypo.ttf", @@ -393,6 +409,10 @@ ); name = "[CP] Copy Pods Resources"; outputPaths = ( + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/api.amplitude.com.der", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ComodoCaLimitedRsaCertificationAuthority.der", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ComodoRsaCA.der", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ComodoRsaDomainValidationCA.der", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GoogleSignIn.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AntDesign.ttf", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Entypo.ttf", @@ -433,6 +453,7 @@ 0BCA495F1EC4B6C600B793EE /* AudioMode.m in Sources */, 0B44A0191F902126009D1D64 /* MPVolumeViewManager.m in Sources */, 0BCA49611EC4B6C600B793EE /* Proximity.m in Sources */, + A480429C21EE335600289B73 /* AmplitudeModule.m in Sources */, C69EFA0C209A0F660027712B /* JMCallKitEmitter.swift in Sources */, C6A34261204EF76800E062DD /* DragGestureController.swift in Sources */, A4A934E9212F3ADB001E9388 /* Dropbox.m in Sources */, diff --git a/ios/sdk/src/analytics/AmplitudeModule.m b/ios/sdk/src/analytics/AmplitudeModule.m new file mode 100644 index 0000000000..cfb3ebe5df --- /dev/null +++ b/ios/sdk/src/analytics/AmplitudeModule.m @@ -0,0 +1,55 @@ +/* + * Copyright @ 2018-present 8x8, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import "Amplitude.h" + +@interface AmplitudeModule : NSObject + +@end + +@implementation AmplitudeModule + +RCT_EXPORT_MODULE(Amplitude) + ++ (BOOL)requiresMainQueueSetup { + return NO; +} + +RCT_EXPORT_METHOD(init:(NSString*)instanceName API_KEY:(NSString*)apiKey) { + [[Amplitude instanceWithName:instanceName] initializeApiKey:apiKey]; +} + +RCT_EXPORT_METHOD(setUserProperties:(NSString*)instanceName userPropsString:(NSDictionary*)userProps) { + if (userProps != nil) { + [[Amplitude instanceWithName:instanceName] setUserProperties:userProps]; + } +} + +RCT_EXPORT_METHOD(logEvent:(NSString*)instanceName eventType:(NSString*)eventType eventPropsString:(NSString*)eventPropsString) { + NSError *error; + NSData *eventPropsData = [eventPropsString dataUsingEncoding:NSUTF8StringEncoding]; + NSDictionary *eventProperties = [NSJSONSerialization JSONObjectWithData:eventPropsData + options:NSJSONReadingMutableContainers + error:&error]; + if (eventProperties == nil) { + NSLog(@"[Amplitude handler] Error parsing event properties: %@", error); + } else { + [[Amplitude instanceWithName:instanceName] logEvent:eventType withEventProperties:eventProperties]; + } +} + +@end diff --git a/react/features/analytics/functions.js b/react/features/analytics/functions.js index 444f41c010..6462e2d390 100644 --- a/react/features/analytics/functions.js +++ b/react/features/analytics/functions.js @@ -6,6 +6,8 @@ import JitsiMeetJS, { } from '../base/lib-jitsi-meet'; import { getJitsiMeetGlobalNS, loadScript } from '../base/util'; +import { AmplitudeHandler } from './handlers'; + const logger = require('jitsi-meet-logger').getLogger(__filename); /** @@ -23,6 +25,16 @@ export function sendAnalytics(event: Object) { } } +/** + * Resets the analytics adapter to its initial state - removes handlers, cache, + * disabled state, etc. + * + * @returns {void} + */ +export function resetAnalytics() { + analytics.reset(); +} + /** * Loads the analytics scripts and inits JitsiMeetJS.analytics by setting * permanent properties and setting the handlers from the loaded scripts. @@ -43,6 +55,9 @@ export function initAnalytics({ getState }: { getState: Function }) { const state = getState(); const config = state['features/base/config']; + const { locationURL } = state['features/base/connection']; + const host = locationURL ? locationURL.host : ''; + const { analytics: analyticsConfig = {}, deploymentInfo @@ -58,6 +73,7 @@ export function initAnalytics({ getState }: { getState: Function }) { envType: (deploymentInfo && deploymentInfo.envType) || 'dev', googleAnalyticsTrackingId, group, + host, product: deploymentInfo && deploymentInfo.product, subproduct: deploymentInfo && deploymentInfo.environment, user: user && user.id, @@ -109,7 +125,7 @@ export function initAnalytics({ getState }: { getState: Function }) { * successfully loaded and rejects if there are no handlers loaded or the * analytics is disabled. */ -function _loadHandlers(scriptURLs, handlerConstructorOptions) { +function _loadHandlers(scriptURLs = [], handlerConstructorOptions) { const promises = []; for (const url of scriptURLs) { @@ -139,12 +155,12 @@ function _loadHandlers(scriptURLs, handlerConstructorOptions) { // check the old location to provide legacy support const analyticsHandlers = [ ...getJitsiMeetGlobalNS().analyticsHandlers, - ...window.analyticsHandlers - ]; + ...window.analyticsHandlers, - if (analyticsHandlers.length === 0) { - throw new Error('No analytics handlers available'); - } + // NOTE: when we add second handler it will be good to put all + // build-in handlers in an array and destruct it here. + AmplitudeHandler + ]; const handlers = []; diff --git a/react/features/analytics/handlers/AmplitudeHandler.js b/react/features/analytics/handlers/AmplitudeHandler.js index cb2b4748e1..d63111bf87 100644 --- a/react/features/analytics/handlers/AmplitudeHandler.js +++ b/react/features/analytics/handlers/AmplitudeHandler.js @@ -1,15 +1,12 @@ -import amplitude from 'amplitude-js'; - -import { getJitsiMeetGlobalNS } from '../../base/util'; - import AbstractHandler from './AbstractHandler'; +import { amplitude } from './amplitude'; const logger = require('jitsi-meet-logger').getLogger(__filename); /** * Analytics handler for Amplitude. */ -class AmplitudeHandler extends AbstractHandler { +export default class AmplitudeHandler extends AbstractHandler { /** * Creates new instance of the Amplitude analytics handler. * @@ -20,18 +17,22 @@ class AmplitudeHandler extends AbstractHandler { constructor(options) { super(); - const { amplitudeAPPKey } = options; + const { amplitudeAPPKey, host } = options; if (!amplitudeAPPKey) { logger.warn( - 'Failed to initialize Amplitude handler, no tracking ID'); + 'Failed to initialize Amplitude handler, no APP key'); return; } this._enabled = true; - amplitude.getInstance().init(amplitudeAPPKey); + this._amplitudeOptions = { + host + }; + + amplitude.getInstance(this._amplitudeOptions).init(amplitudeAPPKey); } /** @@ -42,7 +43,8 @@ class AmplitudeHandler extends AbstractHandler { */ setUserProperties(userProps) { if (this._enabled) { - amplitude.getInstance().setUserProperties(userProps); + amplitude.getInstance(this._amplitudeOptions) + .setUserProperties(userProps); } } @@ -59,13 +61,8 @@ class AmplitudeHandler extends AbstractHandler { return; } - amplitude.getInstance().logEvent( + amplitude.getInstance(this._amplitudeOptions).logEvent( this._extractName(event), event); } } - -const globalNS = getJitsiMeetGlobalNS(); - -globalNS.analyticsHandlers = globalNS.analyticsHandlers || []; -globalNS.analyticsHandlers.push(AmplitudeHandler); diff --git a/react/features/analytics/handlers/amplitude/Amplitude.native.js b/react/features/analytics/handlers/amplitude/Amplitude.native.js new file mode 100644 index 0000000000..7124f1d154 --- /dev/null +++ b/react/features/analytics/handlers/amplitude/Amplitude.native.js @@ -0,0 +1,97 @@ +import { NativeModules } from 'react-native'; + +const { Amplitude: AmplitudeNative } = NativeModules; + +/** + * Wrapper for the Amplitude native module. + */ +class Amplitude { + /** + * Create new Amplitude instance. + * + * @param {string} instanceName - The name of the Amplitude instance. Should + * be used only for multi-project logging. + */ + constructor(instanceName) { + this._instanceName = instanceName; + } + + /** + * Initializes the Amplitude SDK. + * + * @param {string} apiKey - The API_KEY of the Amplitude project. + * @returns {void} + */ + init(apiKey) { + AmplitudeNative.init(this._instanceName, apiKey); + } + + /** + * Sets user properties for the current user. + * + * @param {Object} userProperties - The user properties to be set. + * @returns {void} + */ + setUserProperties(userProperties) { + AmplitudeNative.setUserProperties(this._instanceName, userProperties); + } + + /** + * Log an event with eventType and eventProperties. + * + * @param {string} eventType - The type of the event. + * @param {Object} eventProperties - The properties of the event. + * @returns {void} + */ + logEvent(eventType, eventProperties) { + // The event properties are converted to JSON string because of known + // performance issue when passing objects trough the RN bridge too + // often (a few times a second). + AmplitudeNative.logEvent( + this._instanceName, eventType, JSON.stringify(eventProperties)); + } + +} + +/** + * Cache of Amplitude instances by instanceName. + */ +const instances = {}; + +/** + * The default (with instanceName - undefined) Amplitude instance. + */ +let defaultInstance; + +export default { + /** + * Returns a Amplitude instance. + * + * @param {Object} options - Optional parameters. + * @param {string} options.host - The host property from the current URL. + * @param {string|undefined} options.instanceName - The name of the + * amplitude instance. Should be used only for multi-project logging. + * @returns {Amplitude} + */ + getInstance(options = {}) { + let instance; + + const { host = '', instanceName = '' } = options; + + let internalInstanceName = host; + + if (instanceName !== '') { + internalInstanceName += `-${instanceName}`; + } + + if (internalInstanceName === '') { + instance = defaultInstance = defaultInstance || new Amplitude(); + } else { + instance = instances[internalInstanceName] + = instances[internalInstanceName] + || new Amplitude(internalInstanceName); + } + + return instance; + } +}; diff --git a/react/features/analytics/handlers/amplitude/Amplitude.web.js b/react/features/analytics/handlers/amplitude/Amplitude.web.js new file mode 100644 index 0000000000..449c9d3d20 --- /dev/null +++ b/react/features/analytics/handlers/amplitude/Amplitude.web.js @@ -0,0 +1,7 @@ +import amplitude from 'amplitude-js'; + +export default { + getInstance(options = {}) { + return amplitude.getInstance(options.instanceName); + } +}; diff --git a/react/features/analytics/handlers/amplitude/index.js b/react/features/analytics/handlers/amplitude/index.js new file mode 100644 index 0000000000..ec63cbe22f --- /dev/null +++ b/react/features/analytics/handlers/amplitude/index.js @@ -0,0 +1 @@ +export { default as amplitude } from './Amplitude'; diff --git a/react/features/analytics/handlers/index.js b/react/features/analytics/handlers/index.js new file mode 100644 index 0000000000..9d56d43dc2 --- /dev/null +++ b/react/features/analytics/handlers/index.js @@ -0,0 +1 @@ +export { default as AmplitudeHandler } from './AmplitudeHandler'; diff --git a/react/features/analytics/middleware.js b/react/features/analytics/middleware.js index f0b548a054..74de06b099 100644 --- a/react/features/analytics/middleware.js +++ b/react/features/analytics/middleware.js @@ -1,7 +1,8 @@ import { SET_ROOM } from '../base/conference'; +import { SET_CONFIG } from '../base/config'; import { MiddlewareRegistry } from '../base/redux'; -import { initAnalytics } from './functions'; +import { initAnalytics, resetAnalytics } from './functions'; /** * Middleware which intercepts config actions to handle evaluating analytics @@ -12,6 +13,16 @@ import { initAnalytics } from './functions'; */ MiddlewareRegistry.register(store => next => action => { switch (action.type) { + case SET_CONFIG: { + if (navigator.product === 'ReactNative') { + // Reseting the analytics is currently not needed for web because + // the user will be redirected to another page and new instance of + // Analytics will be created and initialized. + resetAnalytics(); + } + + break; + } case SET_ROOM: { const result = next(action); diff --git a/react/features/base/lib-jitsi-meet/functions.js b/react/features/base/lib-jitsi-meet/functions.js index cd832696e9..9e016099e2 100644 --- a/react/features/base/lib-jitsi-meet/functions.js +++ b/react/features/base/lib-jitsi-meet/functions.js @@ -43,16 +43,7 @@ export function createLocalTrack(type: string, deviceId: string) { * otherwise. */ export function isAnalyticsEnabled(stateful: Function | Object) { - const { - analytics = {}, - disableThirdPartyRequests - } = toState(stateful)['features/base/config']; - const { scriptURLs } = analytics; - - return ( - !disableThirdPartyRequests - && Array.isArray(scriptURLs) - && Boolean(scriptURLs.length)); + return !toState(stateful)['features/base/config'].disableThirdPartyRequests; } /** diff --git a/webpack.config.js b/webpack.config.js index fa80f5a842..c026d27678 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -135,9 +135,7 @@ module.exports = [ './react/features/local-recording/' + 'recording/flac/flacEncodeWorker.js', 'analytics-ga': - './react/features/analytics/handlers/GoogleAnalyticsHandler.js', - 'analytics-amplitude': - './react/features/analytics/handlers/AmplitudeHandler.js' + './react/features/analytics/handlers/GoogleAnalyticsHandler.js' } }),