Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RMET-2732 ::: Merge development with latest ecommerce features #31

Merged
merged 11 commits into from
Jan 11, 2024
Merged
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ The changes documented here do not include those from the original repository.

## [Unreleased]

### 2023-12-22
- Feat: add new e-commerce logging method on Android (https://outsystemsrd.atlassian.net/browse/RMET-2730).

### 2023-12-18
- Feat: Implement e-commerce logging on iOS (https://outsystemsrd.atlassian.net/browse/RMET-2731).

### 2023-12-13
- Feat: add new e-commerce logging method (https://outsystemsrd.atlassian.net/browse/RMET-2729).

## 5.0.0-OS10

### 2023-08-11
Expand Down
38 changes: 34 additions & 4 deletions plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ xmlns:android="http://schemas.android.com/apk/res/android"
</feature>
</config-file>

<dependency id="cordova-plugin-add-swift-support" url="https://github.com/OutSystems/cordova-plugin-add-swift-support.git#2.0.3-OS1"/>

<!--
use a bit hacky method to set boolean value as a string:
https://developer.apple.com/documentation/foundation/nsstring/1409420-boolvalue?preferredLanguage=occ
Expand All @@ -55,6 +57,23 @@ xmlns:android="http://schemas.android.com/apk/res/android"
<header-file src="src/ios/FirebaseAnalyticsPlugin.h" />
<source-file src="src/ios/FirebaseAnalyticsPlugin.m" />

<source-file src="src/ios/Common/Extensions/StringConvertable.swift" target-dir="Common/Extensions" />
<source-file src="src/ios/Common/OSFANLDefaultValues.swift" target-dir="Common" />
<source-file src="src/ios/Common/OSFANLError.swift" target-dir="Common" />
<source-file src="src/ios/Common/OSFANLInputDataFieldKey.swift" target-dir="Common" />

<source-file src="src/ios/InputTransformer/OSFANLInputTransformable.swift" target-dir="InputTransformer" />
<source-file src="src/ios/InputTransformer/OSFANLInputTransformableModel.swift" target-dir="InputTransformer" />
<source-file src="src/ios/InputTransformer/OSFANLInputTransformer.swift" target-dir="InputTransformer" />

<source-file src="src/ios/Manager/OSFANLManageable.swift" target-dir="Manager" />
<source-file src="src/ios/Manager/OSFANLManager.swift" target-dir="Manager" />
<source-file src="src/ios/Manager/OSFANLManager+EventValidationRules.swift" target-dir="Manager" />
<source-file src="src/ios/Manager/OSFANLManagerFactory.swift" target-dir="Manager" />
<source-file src="src/ios/Manager/OSFANLOutputModel.swift" target-dir="Manager" />

<source-file src="src/ios/Validator/OSFANLEventValidator.swift" target-dir="Validator" />

<podspec>
<config>
<source url="https://cdn.cocoapods.org/"/>
Expand All @@ -69,11 +88,10 @@ xmlns:android="http://schemas.android.com/apk/res/android"
<platform name="android">
<preference name="ANDROID_FIREBASE_ANALYTICS_VERSION" default="21.1.1"/>

<hook type="before_plugin_install" src="hooks/android/build_gradle_add_dependency.js" />

<config-file target="res/xml/config.xml" parent="/*">
<feature name="FirebaseAnalytics">
<param name="android-package" value="by.chemerisuk.cordova.firebase.FirebaseAnalyticsPlugin" />
<param name="android-package" value="com.outsystems.plugins.firebase.analytics.FirebaseAnalyticsPlugin" />
<param name="onload" value="$ANALYTICS_COLLECTION_ENABLED" />
</feature>
</config-file>
Expand All @@ -92,8 +110,20 @@ xmlns:android="http://schemas.android.com/apk/res/android"
<framework src="com.google.firebase:firebase-analytics:$ANDROID_FIREBASE_ANALYTICS_VERSION" />
<framework src="build.gradle" custom="true" type="gradleReference" />

<source-file src="src/android/FirebaseAnalyticsPlugin.java"
target-dir="src/by/chemerisuk/cordova/firebase/" />
<source-file src="src/android/com/outsystems/firebase/analytics/FirebaseAnalyticsPlugin.java" target-dir="src/com/outsystems/plugins/firebase/analytics/" />
<source-file src="src/android/com/outsystems/firebase/analytics/model/OSFANLBundle+putAny.kt" target-dir="app/src/main/kotlin/com/outsystems/firebase/analytics/model/" />
<source-file src="src/android/com/outsystems/firebase/analytics/model/OSFANLJSONArray+extension.kt" target-dir="app/src/main/kotlin/com/outsystems/firebase/analytics/model/" />
<source-file src="src/android/com/outsystems/firebase/analytics/model/OSFANLDefaultValues.kt" target-dir="app/src/main/kotlin/com/outsystems/firebase/analytics/model/" />
<source-file src="src/android/com/outsystems/firebase/analytics/model/OSFANLError.kt" target-dir="app/src/main/kotlin/com/outsystems/firebase/analytics/model/" />
<source-file src="src/android/com/outsystems/firebase/analytics/model/OSFANLEventOutputModel.kt" target-dir="app/src/main/kotlin/com/outsystems/firebase/analytics/model/" />
<source-file src="src/android/com/outsystems/firebase/analytics/model/OSFANLInputDataFieldKey.kt" target-dir="app/src/main/kotlin/com/outsystems/firebase/analytics/model/" />

<source-file src="src/android/com/outsystems/firebase/analytics/validator/OSFANLEventItemsValidator.kt" target-dir="app/src/main/kotlin/com/outsystems/firebase/analytics/validator/" />
<source-file src="src/android/com/outsystems/firebase/analytics/validator/OSFANLEventParameterValidator.kt" target-dir="app/src/main/kotlin/com/outsystems/firebase/analytics/validator/" />
<source-file src="src/android/com/outsystems/firebase/analytics/validator/OSFANLMinimumRequired.kt" target-dir="app/src/main/kotlin/com/outsystems/firebase/analytics/validator/" />

<source-file src="src/android/com/outsystems/firebase/analytics/OSFANLManager.kt" target-dir="app/src/main/kotlin/com/outsystems/firebase/analytics/" />

</platform>

</plugin>
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package by.chemerisuk.cordova.firebase;
package com.outsystems.plugins.firebase.analytics;

import android.content.Context;
import android.os.Bundle;
Expand All @@ -8,6 +8,9 @@
import by.chemerisuk.cordova.support.ReflectiveCordovaPlugin;

import com.google.firebase.analytics.FirebaseAnalytics;
import com.outsystems.firebase.analytics.OSFANLManager;
import com.outsystems.firebase.analytics.model.OSFANLError;
import com.outsystems.firebase.analytics.model.OSFANLEventOutputModel;

import org.apache.cordova.CallbackContext;
import org.json.JSONException;
Expand All @@ -21,19 +24,18 @@ public class FirebaseAnalyticsPlugin extends ReflectiveCordovaPlugin {

private FirebaseAnalytics firebaseAnalytics;

private OSFANLManager manager = new OSFANLManager();

@Override
protected void pluginInitialize() {
Log.d(TAG, "Starting Firebase Analytics plugin");

Context context = this.cordova.getActivity().getApplicationContext();

this.firebaseAnalytics = FirebaseAnalytics.getInstance(context);
}

@CordovaMethod
private void logEvent(String name, JSONObject params, CallbackContext callbackContext) throws JSONException {
this.firebaseAnalytics.logEvent(name, parse(params));

callbackContext.success();
}

Expand Down Expand Up @@ -87,6 +89,20 @@ private void requestTrackingAuthorization(JSONObject params, CallbackContext cal
callbackContext.success();
}

@CordovaMethod
private void logECommerceEvent(JSONObject params, CallbackContext callbackContext) throws JSONException {
try {
OSFANLEventOutputModel output = manager.buildOutputEventFromInputJSON(params);
this.firebaseAnalytics.logEvent(output.getName(), output.getParameters());
callbackContext.success();
} catch (OSFANLError e) {
JSONObject result = new JSONObject();
result.put("code", e.getCode());
result.put("message", e.getMessage());
callbackContext.error(result);
}
}

private static Bundle parse(JSONObject params) throws JSONException {
Bundle bundle = new Bundle();
Iterator<String> it = params.keys();
Expand Down
160 changes: 160 additions & 0 deletions src/android/com/outsystems/firebase/analytics/OSFANLManager.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package com.outsystems.firebase.analytics

import android.os.Bundle
import com.google.firebase.analytics.FirebaseAnalytics
import com.outsystems.firebase.analytics.model.OSFANLError
import com.outsystems.firebase.analytics.model.OSFANLEventOutputModel
import com.outsystems.firebase.analytics.model.OSFANLInputDataFieldKey
import com.outsystems.firebase.analytics.model.OSFANLInputDataFieldKey.EVENT
import com.outsystems.firebase.analytics.model.OSFANLInputDataFieldKey.ITEMS
import com.outsystems.firebase.analytics.model.OSFANLInputDataFieldKey.SHIPPING
import com.outsystems.firebase.analytics.model.OSFANLInputDataFieldKey.TAX
import com.outsystems.firebase.analytics.model.OSFANLInputDataFieldKey.TRANSACTION_ID
import com.outsystems.firebase.analytics.model.OSFANLInputDataFieldKey.VALUE
import com.outsystems.firebase.analytics.model.getArrayOrEmpty
import com.outsystems.firebase.analytics.model.getStringOrNull
import com.outsystems.firebase.analytics.validator.OSFANLEventItemsValidator
import com.outsystems.firebase.analytics.validator.OSFANLEventParameterValidator
import com.outsystems.firebase.analytics.validator.OSFANLMinimumRequired.AT_LEAST_ONE
import com.outsystems.firebase.analytics.validator.OSFANLMinimumRequired.ONE
import org.json.JSONArray
import org.json.JSONObject
import java.io.Serializable

class OSFANLManager {

@Throws(OSFANLError::class)
fun buildOutputEventFromInputJSON(input: JSONObject): OSFANLEventOutputModel {

val eventName = input.getStringOrNull(OSFANLInputDataFieldKey.EVENT.json) ?: throw OSFANLError.missing(EVENT.json)
val parameters = input.getArrayOrEmpty(OSFANLInputDataFieldKey.EVENT_PARAMETERS.json)
val items = input.getArrayOrEmpty(ITEMS.json)

val eventBuilderMethod = getEventBuilderMethod(eventName)
val eventBundle = eventBuilderMethod(this, parameters, items)

return OSFANLEventOutputModel(eventName, eventBundle)
}

private fun getEventBuilderMethod(
eventName: String
): (OSFANLManager, JSONArray, JSONArray) -> Bundle {

when (eventName) {

FirebaseAnalytics.Event.PURCHASE ->
return OSFANLManager::buildBundleForPurchaseParametersEventType

FirebaseAnalytics.Event.REFUND ->
return OSFANLManager::buildBundleForRefundParametersEventType

FirebaseAnalytics.Event.SELECT_ITEM ->
return OSFANLManager::buildBundleForOneItemParametersEventType

FirebaseAnalytics.Event.SELECT_PROMOTION ->
return OSFANLManager::buildBundleForSelectPromotionParametersEventType

FirebaseAnalytics.Event.VIEW_ITEM_LIST ->
return OSFANLManager::buildBundleForViewItemListParametersEventType

FirebaseAnalytics.Event.VIEW_PROMOTION ->
return OSFANLManager::buildBundleForOneItemParametersEventType

else ->
return OSFANLManager::buildBundleForValueCurrencyAndMultipleItemsEventType
}
}

private fun buildBundleForValueCurrencyAndMultipleItemsEventType(
parameters: JSONArray,
items: JSONArray
): Bundle {
return buildAndValidateParameterBundle(
parameters,
items,
OSFANLEventParameterValidator.Builder()
.requireCurrencyValue()
.build(),
OSFANLEventItemsValidator(minLimit = AT_LEAST_ONE)
)
}

private fun buildBundleForPurchaseParametersEventType(
parameters: JSONArray,
items: JSONArray
): Bundle {
return buildAndValidateParameterBundle(
parameters,
items,
OSFANLEventParameterValidator.Builder()
.requireCurrencyValue()
.required(TRANSACTION_ID)
.number(SHIPPING, TAX)
.build(),
OSFANLEventItemsValidator(minLimit = AT_LEAST_ONE)
)
}

private fun buildBundleForRefundParametersEventType(
parameters: JSONArray,
items: JSONArray
): Bundle {
return buildAndValidateParameterBundle(
parameters,
items,
OSFANLEventParameterValidator.Builder()
.requireCurrencyValue()
.required(TRANSACTION_ID)
.number(SHIPPING, TAX)
.build()
)
}

private fun buildBundleForOneItemParametersEventType(
parameters: JSONArray,
items: JSONArray
): Bundle {
return buildAndValidateParameterBundle(
parameters,
items,
itemsValidator = OSFANLEventItemsValidator(minLimit = ONE)
)
}

private fun buildBundleForSelectPromotionParametersEventType(
parameters: JSONArray,
items: JSONArray
): Bundle {
return buildAndValidateParameterBundle(parameters, items)
}

private fun buildBundleForViewItemListParametersEventType(
parameters: JSONArray,
items: JSONArray
): Bundle {
return buildAndValidateParameterBundle(
parameters,
items,
itemsValidator = OSFANLEventItemsValidator(minLimit = AT_LEAST_ONE)
)
}

private fun buildAndValidateParameterBundle(
parameters: JSONArray,
items: JSONArray,
parametersValidator: OSFANLEventParameterValidator = OSFANLEventParameterValidator.Builder().build(),
itemsValidator: OSFANLEventItemsValidator = OSFANLEventItemsValidator()
): Bundle {

// validate parameters
val parameterBundle = parametersValidator.validate(parameters)

// validate items
val itemsBundle = itemsValidator.validate(items)
if(itemsBundle.isNotEmpty())
parameterBundle.putSerializable(ITEMS.json, itemsBundle as Serializable)

return parameterBundle
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.outsystems.firebase.analytics.model

import android.os.Bundle

/**
* Adds a range of different types to a bundle. Accepted types are String, Int, Double and Long
* @param key the key in which to store the value
* @param value the value to store
*/
fun Bundle.putAny(key: String, value: Any) {
when (value) {
is String -> this.putString(key, value)
is Int -> this.putInt(key, value)
is Double -> this.putDouble(key, value)
is Long -> this.putLong(key, value)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.outsystems.firebase.analytics.model

/**
* Holds the default size values for the input data
*/
class OSFANLDefaultValues {
companion object {
const val itemQuantity: Int = 1
const val itemCustomParametersMaximum: Int = 27
const val eventItemsMaximum: Int = 200
}
}
Loading
Loading