Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/daily.yml
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,8 @@ jobs:
run: ./gradlew lint -c settings-kits.gradle -Pmparticle.kit.mparticleFromMavenLocalOnly=true
- name: "Run Isolated Kit Lint (urbanairship-kit)"
run: ./gradlew -Pmparticle.kit.mparticleFromMavenLocalOnly=true -p kits/urbanairship/urbanairship-20 lint
- name: "Run Isolated Kit Lint (braze-43)"
run: ./gradlew -Pmparticle.kit.mparticleFromMavenLocalOnly=true -p kits/braze/braze-43 lint
- name: "Run Isolated Kit Lint (ga-kit)"
run: ./gradlew -Pmparticle.kit.mparticleFromMavenLocalOnly=true -p kits/ga/ga-23 lint
- name: "Run Isolated Kit Lint (ga4-kit)"
Expand Down Expand Up @@ -283,6 +285,8 @@ jobs:
run: ./gradlew ktlintCheck -c settings-kits.gradle -Pmparticle.kit.mparticleFromMavenLocalOnly=true
- name: "Run Isolated Kit Kotlin Lint (urbanairship-kit)"
run: ./gradlew -Pmparticle.kit.mparticleFromMavenLocalOnly=true -p kits/urbanairship/urbanairship-20 ktlintCheck
- name: "Run Isolated Kit Kotlin Lint (braze-43)"
run: ./gradlew -Pmparticle.kit.mparticleFromMavenLocalOnly=true -p kits/braze/braze-43 ktlintCheck
- name: "Run Isolated Kit Kotlin Lint (ga-kit)"
run: ./gradlew -Pmparticle.kit.mparticleFromMavenLocalOnly=true -p kits/ga/ga-23 ktlintCheck
- name: "Run Isolated Kit Kotlin Lint (ga4-kit)"
Expand Down Expand Up @@ -329,6 +333,8 @@ jobs:
run: ./gradlew clean testRelease -c settings-kits.gradle -Pmparticle.kit.mparticleFromMavenLocalOnly=true
- name: "Test Isolated Kits (urbanairship-kit)"
run: ./gradlew -Pmparticle.kit.mparticleFromMavenLocalOnly=true -p kits/urbanairship/urbanairship-20 clean testRelease
- name: "Test Isolated Kits (braze-43)"
run: ./gradlew -Pmparticle.kit.mparticleFromMavenLocalOnly=true -p kits/braze/braze-43 clean testRelease
Comment thread
BrandonStalnaker marked this conversation as resolved.
- name: "Test Isolated Kits (ga-kit)"
run: ./gradlew -Pmparticle.kit.mparticleFromMavenLocalOnly=true -p kits/ga/ga-23 clean testRelease
- name: "Test Isolated Kits (ga4-kit)"
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ jobs:
run: ./gradlew -p kits testRelease -c ../settings-kits.gradle -Pmparticle.kit.mparticleFromMavenLocalOnly=true
- name: "Run Isolated Kit Compatibility Tests (urbanairship)"
run: ./gradlew -Pmparticle.kit.mparticleFromMavenLocalOnly=true -p kits/urbanairship/urbanairship-20 -PisRelease=true testRelease
- name: "Run Isolated Kit Compatibility Tests (braze-43)"
run: ./gradlew -Pmparticle.kit.mparticleFromMavenLocalOnly=true -p kits/braze/braze-43 -PisRelease=true testRelease
- name: "Run Isolated Kit Compatibility Tests (ga)"
run: ./gradlew -Pmparticle.kit.mparticleFromMavenLocalOnly=true -p kits/ga/ga-23 -PisRelease=true testRelease
- name: "Run Isolated Kit Compatibility Tests (ga4)"
Expand Down
14 changes: 14 additions & 0 deletions .github/workflows/release-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,20 @@ jobs:
- name: Publish kits to Maven Central
run: ./gradlew publishMavenPublicationToMavenCentralRepository -PVERSION=${{ needs.setup-and-version.outputs.final_version }} -c settings-kits.gradle --no-build-cache

# Isolated Kotlin 2.2.x kits are excluded from settings-kits.gradle and must be
# published from their own project roots (same pattern as CI test/lint steps).
- name: Publish Isolated Kits (urbanairship-20)
run: ./gradlew -p kits/urbanairship/urbanairship-20 -PisRelease=true -PVERSION=${{ needs.setup-and-version.outputs.final_version }} publishMavenPublicationToMavenCentralRepository --no-build-cache

- name: Publish Isolated Kits (braze-43)
run: ./gradlew -p kits/braze/braze-43 -PisRelease=true -PVERSION=${{ needs.setup-and-version.outputs.final_version }} publishMavenPublicationToMavenCentralRepository --no-build-cache

- name: Publish Isolated Kits (ga-23)
run: ./gradlew -p kits/ga/ga-23 -PisRelease=true -PVERSION=${{ needs.setup-and-version.outputs.final_version }} publishMavenPublicationToMavenCentralRepository --no-build-cache

- name: Publish Isolated Kits (ga4-23)
run: ./gradlew -p kits/ga4/ga4-23 -PisRelease=true -PVERSION=${{ needs.setup-and-version.outputs.final_version }} publishMavenPublicationToMavenCentralRepository --no-build-cache

# rokt-sdk-plus (com.rokt:rokt-sdk-plus) is an umbrella over the mParticle Rokt kit + the
# Rokt Payment Extension. The "Publish core to Maven local" step above already placed
# android-core/android-kit-base/android-kit-plugin in mavenLocal; we also need the Rokt
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@

- Add Rokt Shoppable Ads payment extension registration and selection APIs.
- Add the `com.rokt:rokt-sdk-plus` umbrella artifact: a single dependency bundling the mParticle core SDK, the mParticle Rokt kit, and the Rokt Payment Extension (Shoppable Ads), mirroring the iOS `RoktSDKPlus` umbrella.
- Add a `braze-43` kit track supporting Braze Android SDK 43.x, with an opt-in `useEcommerceRecommendedEvents` setting that forwards mParticle commerce events using Braze's recommended eCommerce event schema (`ecommerce.cart_updated`, `ecommerce.checkout_started`, `ecommerce.product_viewed`, `ecommerce.order_placed`, `ecommerce.order_refunded`). Typed `subtotalValue`, `tax`, and `shipping` fields are populated from the kit `subtotalValueAttribute` mapping and `TransactionAttributes`. Cart/checkout IDs and product image/product URLs are resolved from kit attribute mappings (`cartIdAttribute`, `checkoutIdAttribute`, `imageUrlAttribute`, `productUrlAttribute`); kit `source` is used as a direct value when set (default `"android"`). Legacy commerce forwarding remains the default. The `braze-43` track is built standalone (Kotlin 2.2.x) and published from an isolated release step.

### Changed

- Rename the `braze-43` kit entry class from `AppboyKit` to `BrazeKit` (`getName()` now returns `"Braze"`). A deprecated `AppboyKit` subclass is retained so `KitIntegrationFactory` can still load `com.mparticle.kits.AppboyKit`.
- Upgrade Kotlin to 2.1.20 across the core SDK, buildSrc, and all integrated kits.
- Add support for qualified alpha, beta, and release candidate versions in release workflows.
- Add Kotlin `MParticle.rokt` access and `RoktLayout` event callbacks for the Rokt kit.
Expand Down
8 changes: 7 additions & 1 deletion ONBOARDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ Kotlin version.
**Currently isolated:**

- `kits/urbanairship/urbanairship-20` (Kotlin 2.2.x, `urbanairship-core:20.3.0`)
- `kits/braze/braze-43` (Kotlin 2.2.x, `com.braze:android-sdk-ui:[43.0.0,44.0.0)`)
- `kits/ga/ga-23` (Kotlin 2.2.x, `firebase-analytics:23.x`)
- `kits/ga4/ga4-23` (Kotlin 2.2.x, `firebase-analytics:23.x`)

Expand All @@ -166,7 +167,12 @@ cd kits/urbanairship/urbanairship-20 && ./gradlew -PisRelease=true testRelease
**Adding a new isolated kit:** If a kit upgrades to a Kotlin version
incompatible with the root KGP (2.1.20), remove it from
`settings-kits.gradle` with a comment, and add standalone build steps
to the CI workflows following the urbanairship pattern.
to the CI workflows following the urbanairship pattern. Also add a
matching isolated publish step in `.github/workflows/release-publish.yml`
(the aggregate `settings-kits.gradle` publish will not include it).
If the kit's standalone `rootProject.name` differs from the Maven
artifact id consumers expect, set `mparticleMavenPublish.artifactId`
explicitly in the kit `build.gradle` (see `braze-43`).

## Read More

Expand Down
98 changes: 98 additions & 0 deletions kits/braze/braze-43/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Braze (formerly Appboy) Kit Integration

This directory contains the [Braze](https://www.braze.com/) integration for the [mParticle Android SDK](https://github.com/mParticle/mparticle-android-sdk).

This `braze-43` kit track targets **Braze Android SDK 43.x** (`com.braze:android-sdk-ui:[43.0.0,44.0.0)`). Because Braze 43 requires Kotlin 2.2.x, this track is built standalone from the rest of the mParticle SDK (see the repository `ONBOARDING.md`).

## Recommended eCommerce Events (opt-in)

Braze 42.3.0+ introduces [recommended eCommerce events](https://www.braze.com/docs/developer_guide/analytics/logging_ecommerce_events/#android); Braze 43.0.0 adds typed `subtotalValue`, `tax`, and `shipping` fields on cart, checkout, and order events. This kit can forward mParticle commerce events using that schema when the connection setting **`useEcommerceRecommendedEvents`** is enabled. When the setting is off (the default), commerce forwarding is unchanged and fully backward compatible.

When enabled, supported mParticle commerce actions map to Braze recommended events:

| mParticle commerce action | Braze recommended event |
| :------------------------ | :------------------------------------------------------------ |
| `add_to_cart` | `ecommerce.cart_updated` (action `add`) |
| `remove_from_cart` | `ecommerce.cart_updated` (action `remove`) |
| `checkout` | `ecommerce.checkout_started` |
| `view_detail` | `ecommerce.product_viewed` (one per product) |
| `purchase` | `ecommerce.order_placed` |
| `refund` | `ecommerce.order_refunded` (custom event; no typed Braze API) |

Requirements and behavior:

- **Minimum Braze Android SDK version: 43.0.0** (recommended eCommerce APIs plus typed `subtotalValue`/`tax`/`shipping`). Any commerce action not in the table above continues to use legacy forwarding.
- `TransactionAttributes.tax` / `shipping` map to Braze's typed `tax` / `shipping` fields.
- Cart/checkout IDs, subtotal, and product image/product URLs are resolved from kit attribute mappings (`cartIdAttribute`, `checkoutIdAttribute`, `subtotalValueAttribute`, `imageUrlAttribute`, `productUrlAttribute`). Each mapping's JSON `value` field is the mParticle attribute name to look up on the commerce event or product. Plain attribute-name strings are also accepted for local/test configs.
- Kit setting `source` is used as a direct Braze `source` value when set; otherwise `"android"`.
- `total_discounts` continues to be read from a commerce custom attribute named `total_discounts` (not kit-mapped).
- Attributes without a direct Braze equivalent (`affiliation`, product `brand`/`category`/`coupon_code`/`position`, etc.) are placed inside the event- or product-level `metadata` object, per Braze's strict recommended-event schema. Mapped attribute names that were promoted to typed fields are excluded from metadata.
- `cartId`/`checkoutId` fall back to the current mParticle session id and then a generated UUID when unmapped or missing. Image/product URLs are `null` when their mappings are unset or the mapped attribute is absent.

## Example App

This repository contains an [example app](example) showing how to implement mParticle, Braze, and Firebase Cloud Messaging. The key changes you need to make to your app are below, and please also reference mParticle and Braze's documentation:

- [Instrumenting Push](https://docs.mparticle.com/developers/sdk/android/push-notifications)
- [Braze Documentation](https://docs.mparticle.com/integrations/braze/event)

## 1. Adding the integration

[See a full build.gradle example here](https://github.com/mparticle-integrations/mparticle-android-integration-appboy/blob/master/example/build.gradle)

1. Ensure `mavenCentral()` is included in your repositories (Braze is hosted on Maven Central; the legacy Appboy GitHub Pages Maven repo is not required):

```groovy
repositories {
mavenCentral()
google()
...
}
```

2. Add the kit dependency to your app's `build.gradle`:

```groovy
dependencies {
implementation 'com.mparticle:braze-43:6+'
}
```

## 2. Registering for Push

mParticle's SDK takes care of registering for push notifications and passing tokens or instance IDs to the Braze SDK. [Follow the mParticle push notification documentation](https://docs.mparticle.com/developers/sdk/android/push-notifications#register-for-push-notifications) to instrument the SDK for push registration. You can skip over [this section of Braze's documentation](https://www.braze.com/docs/developer_guide/platform_integration_guides/android/push_notifications/integration/#registering-for-push).

## 3. Displaying Push

[See a full example of an AndroidManifest.xml here](https://github.com/mparticle-integrations/mparticle-android-integration-appboy/blob/master/example/src/main/AndroidManifest.xml).

mParticle's SDK also takes care of capturing incoming push notifications and passing the resulting `Intent` to Braze's `BrazePushReceiver`. Follow the [mParticle push notification documentation](https://docs.mparticle.com/developers/sdk/android/push-notifications#display-push-notifications) to ensure you add the correct services and receivers to your app's AndroidManifest.xml.

## 4. Reacting to Push and Deeplinking

There are a wide variety of implementation options available in Braze to deeplink a user when they tap a notification. There are **two specific requirements** to ensure automatic deeplinking works as intended.

- `BrazePushReceiver`

Whereas up until now you should have nothing Braze-specific in your `AndroidManifest.xml`, using Braze's automatic deeplinking does require you to add their `BrazePushReceiver`. Note that you do not need to specify any Intent filters (for example to receive push tokens, since mParticle takes care of that). You just need to add the following:

```xml
<receiver android:name="com.braze.push.BrazePushReceiver" />
```

- `braze.xml`

For automatic deep-linking, you need to add a boolean resource named `com_braze_handle_push_deep_links_automatically`. This can be in any resource file, or you can name it `braze.xml`:

```xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="com_braze_handle_push_deep_links_automatically">true</bool>
</resources>
```

From here you should be able to successfully test push via Braze! Braze offers many client-side configurable options via xml resources and otherwise. Please see review the rest of [their documentation here](https://www.braze.com/docs/developer_guide/platform_integration_guides/android/push_notifications/integration/#step-3-add-deep-links) for more information.

## License

[Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0)
82 changes: 82 additions & 0 deletions kits/braze/braze-43/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
buildscript {
ext.kotlin_version = '2.2.20'
if (!project.hasProperty('version') || project.version.equals('unspecified')) {
project.version = '+'
}

repositories {
google()
mavenLocal()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.1.4'
classpath 'com.mparticle:android-kit-plugin:' + project.version
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}

plugins {
id "org.sonarqube" version "3.5.0.2730"
id "org.jlleitschuh.gradle.ktlint" version "13.0.0"
}

sonarqube {
properties {
property "sonar.projectKey", "mparticle-android-integration-braze-43"
property "sonar.organization", "mparticle"
property "sonar.host.url", "https://sonarcloud.io"
}
}

apply plugin: 'org.jlleitschuh.gradle.ktlint'
apply plugin: 'kotlin-android'
apply plugin: 'com.mparticle.kit'

// Standalone builds use rootProject.name "android-braze-kit"; force the published
// Maven coordinate consumers expect (com.mparticle:braze-43).
if (extensions.findByName('mparticleMavenPublish') != null) {
mparticleMavenPublish {
artifactId.set('braze-43')
description.set('Braze 43 kit for the mParticle SDK')
}
}

android {
namespace 'com.mparticle.kits.braze43'
buildFeatures {
buildConfig = true
}
defaultConfig {
minSdkVersion 21
}
lint {
// Workaround for lint internal crash
abortOnError false
// Ignore obsolete custom lint checks from older fragment library
disable 'ObsoleteLintCustomCheck'
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = '17'
}
testOptions {
unitTests.all {
jvmArgs += ['--add-opens', 'java.base/java.lang=ALL-UNNAMED']
}
}
}

repositories {
mavenLocal()
mavenCentral()
}

dependencies {
compileOnly 'com.google.firebase:firebase-messaging:[10.2.1, )'
api 'com.braze:android-sdk-ui:[43.0.0,44.0.0)'
testImplementation files('libs/java-json.jar')
}
3 changes: 3 additions & 0 deletions kits/braze/braze-43/consumer-proguard.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Braze ships its own consumer ProGuard/R8 rules via android-sdk-ui.
# Because this kit declares Braze as an `api` dependency, those rules are
# applied transitively to consuming apps — no kit-level Braze keeps needed.
65 changes: 65 additions & 0 deletions kits/braze/braze-43/example/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
*
* Example app build.gradle for using mParticle + Braze + Firebase Cloud Messaging
* Please see the inline comments below.
*
*/


apply plugin: 'com.android.application'

android {
compileSdk 31

defaultConfig {
applicationId "com.mparticle.kits.braze.example"
minSdk 16
targetSdk 31
versionCode 1
versionName "1.0"

testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

}

buildTypes {
release {
minifyEnabled false
}
}
}

repositories {
mavenCentral()
google()
}

buildscript {
repositories {
//REQUIRED: com.google.gms:google-services requires both jCenter and Google's Maven :rollseyes:
mavenCentral()
google()
}
dependencies {
classpath 'com.google.gms:google-services:4.2.0' //REQUIRED for Firebase
}
}
dependencies {
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:support-v4:28.0.0'
implementation 'com.android.support:support-media-compat:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'

// REQUIRED: Add the Braze (formerly Appboy) kit here
// this will also pull in mParticle's Core SDK (com.mparticle:android-core) as a transitive dependency
implementation 'com.mparticle:braze-43:6+'

// REQUIRED for Firebase
implementation 'com.google.firebase:firebase-messaging:17.3.4'

// Not strictly required but strongly recommended so that mParticle and Braze can query for the Android Advertising ID
implementation 'com.google.android.gms:play-services-ads-identifier:16.0.0'

}

apply plugin: 'com.google.gms.google-services' //REQUIRED for Firebase
38 changes: 38 additions & 0 deletions kits/braze/braze-43/example/example-kotlin/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}

android {
namespace 'com.mparticle.kits.braze.braze43.example.kotlin'
compileSdk 35

defaultConfig {
applicationId 'com.mparticle.kits.braze.braze43.example.kotlin'
minSdk 21
targetSdk 35
versionCode 1
versionName '1.0'
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}

kotlinOptions {
jvmTarget = '17'
}

buildTypes {
release {
minifyEnabled false
}
}
}

dependencies {
implementation project(':kits:braze:braze-43')
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.11.0'
}
Loading
Loading