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
48 changes: 46 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ jobs:
- name: Setup code
uses: maxim-lobanov/setup-xcode@ed7a3b1fda3918c0306d1b724322adc0b8cc0a90 # v1
with:
xcode-version: '15.4'
xcode-version: '16.2'
- name: Checkout code
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Setup Flutter
Expand All @@ -139,6 +139,28 @@ jobs:
channel: 'stable'
- name: Get dependencies
run: flutter pub get
- name: Create stub GoogleService-Info.plist for CI
run: |
cat > example/ios/Runner/GoogleService-Info.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>API_KEY</key><string>AIzaCI00000000000000000000000000000000</string>
<key>GCM_SENDER_ID</key><string>000000000000</string>
<key>PLIST_VERSION</key><string>1</string>
<key>BUNDLE_ID</key><string>com.placeholder.ci</string>
<key>PROJECT_ID</key><string>placeholder-ci</string>
<key>STORAGE_BUCKET</key><string>placeholder-ci.appspot.com</string>
<key>IS_ADS_ENABLED</key><false/>
<key>IS_ANALYTICS_ENABLED</key><false/>
<key>IS_APPINVITE_ENABLED</key><true/>
<key>IS_GCM_ENABLED</key><true/>
<key>IS_SIGNIN_ENABLED</key><true/>
<key>GOOGLE_APP_ID</key><string>1:000000000000:ios:0000000000000000000000</string>
</dict>
</plist>
EOF
- name: Setup Pods
working-directory: ./example/ios
run: pod install
Expand Down Expand Up @@ -199,7 +221,7 @@ jobs:
- name: Setup code
uses: maxim-lobanov/setup-xcode@ed7a3b1fda3918c0306d1b724322adc0b8cc0a90 # v1
with:
xcode-version: '15.4'
xcode-version: '16.2'
- name: Checkout code
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Setup Flutter
Expand All @@ -209,6 +231,28 @@ jobs:
channel: 'stable'
- name: Get dependencies
run: flutter pub get
- name: Create stub GoogleService-Info.plist for CI
run: |
cat > example/ios/Runner/GoogleService-Info.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>API_KEY</key><string>AIzaCI00000000000000000000000000000000</string>
<key>GCM_SENDER_ID</key><string>000000000000</string>
<key>PLIST_VERSION</key><string>1</string>
<key>BUNDLE_ID</key><string>com.placeholder.ci</string>
<key>PROJECT_ID</key><string>placeholder-ci</string>
<key>STORAGE_BUCKET</key><string>placeholder-ci.appspot.com</string>
<key>IS_ADS_ENABLED</key><false/>
<key>IS_ANALYTICS_ENABLED</key><false/>
<key>IS_APPINVITE_ENABLED</key><true/>
<key>IS_GCM_ENABLED</key><true/>
<key>IS_SIGNIN_ENABLED</key><true/>
<key>GOOGLE_APP_ID</key><string>1:000000000000:ios:0000000000000000000000</string>
</dict>
</plist>
EOF
- name: Build
working-directory: ./example
run: flutter build ios --debug --no-codesign --simulator
Expand Down
4 changes: 4 additions & 0 deletions example/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,7 @@ app.*.symbols

# Obfuscation related
app.*.map.json

# Firebase config files — kept locally, not committed
android/app/google-services.json
ios/Runner/GoogleService-Info.plist
165 changes: 151 additions & 14 deletions example/README.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,173 @@
# Usercentrics SDK for Flutter - Quickstart
# Usercentrics SDK for Flutter — Example App

The goal of this project is to show how to use Usercentrics SDK inside of a Flutter application.
This app demonstrates how to integrate and test the Usercentrics SDK in a Flutter application, including consent mediation with Firebase Analytics.

## Instructions
---

This project is a starting point for a Flutter application.
## Prerequisites

- Step 1: Clone the repository
- [Flutter SDK](https://docs.flutter.dev/get-started/install) installed
- For iOS: Xcode + CocoaPods (`gem install cocoapods`)
- For Android: Android Studio or a connected device/emulator

- Step 2: Get the dependencies by executing `flutter pub get`
---

- Step 3: Run the application by executing `flutter run`
## Running the App (without Consent Mediation)

## Result
No Firebase setup is required for the standard flow.

**Step 1 — Clone the repository**
```bash
git clone https://github.com/Usercentrics/flutter-sdk.git
cd flutter-sdk
```

**Step 2 — Install dependencies**
```bash
flutter pub get
```

**Step 3 — iOS only: install pods**

> **Note:** The iOS Podfile includes a local path override for `UsercentricsUI` pointing to
> `../../../mobile-sdk/platforms/ios/UsercentricsUI`. This is used for testing local
> mobile-sdk changes without a full release. If you do not have the `mobile-sdk` repository
> checked out at that relative path, remove or comment out that line in `example/ios/Podfile`
> before running `pod install`:
> ```ruby
> # pod 'UsercentricsUI', :path => '../../../mobile-sdk/platforms/ios/UsercentricsUI'
> ```

```bash
cd example/ios && pod install && cd ../..
```

**Step 4 — Run the app**
```bash
cd example && flutter run
```

> **Note:** Consent mediation is **enabled by default** in this example app
> (`_kMediationTestEnabled = true`). To run without mediation, pass the flag explicitly:
> ```bash
> flutter run --dart-define=MEDIATION_TEST=false
> ```
> Without Firebase config files in place, the app will still run but Firebase will not
> initialise — you will see an error in the logs. Add the config files as described below
> to test mediation end-to-end.

---

## App Features

After running the app you should see a screen like this:

<img src="screenshot-main.png" height="534" width="300"/>

### UsercentricsUI

The default Usercentrics-provided consent banner.

<img src="screenshot-usercentrics-ui.png" height="534" width="300"/>

### CustomUI
### Custom UI

Build your own consent UI using the raw consent data from the SDK.

<img src="screenshot-custom-ui.png" height="534" width="300"/>

### Consent Mediation
### Customization Examples

Two built-in examples (`Customization Example 1` and `Customization Example 2`) show how to customise the banner appearance — fonts, colours, button layouts, and layer settings — using `BannerSettings`.

### Webview Integration

Demonstrates how to inject the user's Usercentrics session data into a `WebView` so the Browser CMP can pick up the native consent without asking the user again.

### GPP Testing

A dedicated screen for testing the Global Privacy Platform (GPP) API:
- Fetch and display the encoded GPP string
- Fetch full GPP data (applicable sections and field values)
- Set consent values for specific GPP sections (e.g. `usnat`, `usfl`)
- Monitor real-time `onGppSectionChange` stream events

---

## Running the App with Consent Mediation

Consent mediation automatically forwards the user's consent decisions to integrated third-party SDKs (e.g. Firebase Analytics). Testing this requires Firebase to be configured in the app.

### Step 1 — Create a Firebase project

1. Go to the [Firebase Console](https://console.firebase.google.com)
2. Click **Add project** and follow the setup wizard
3. Once the project is created, register two apps (Android + iOS) in the next steps

### Step 2 — Register the Android app and download `google-services.json`

1. In your Firebase project, click **Add app** → select **Android**
2. Enter the package name: `com.usercentrics.sdk.mediation.test`
3. Click **Register app**
4. Download the `google-services.json` file
5. Place it at:
```
example/android/app/google-services.json
```

### Step 3 — Register the iOS app and download `GoogleService-Info.plist`

1. In your Firebase project, click **Add app** → select **iOS**
2. Enter the bundle ID: `com.usercentrics.sdk.mediation.test`
3. Click **Register app**
4. Download the `GoogleService-Info.plist` file
5. Place it at:
```
example/ios/Runner/GoogleService-Info.plist
```

> **Note:** Both config files are excluded from version control (`.gitignore`) as they
> contain API keys. You must add them locally before running the app with mediation.

### Step 4 — Run the app

Since mediation is enabled by default, simply run:

```bash
cd example && flutter run
```

To explicitly disable mediation:

```bash
cd example && flutter run --dart-define=MEDIATION_TEST=false
```

### Step 5 — Test consent mediation

1. Tap **Initialize SDK** — the Usercentrics CMP will appear
2. Accept or deny consent
3. Check the debug logs — you should see mediation output like:
```
[USERCENTRICS][DEBUG] [Mediation] Firebase - Consent applied successfully.
```

> **Important:** Consent is persisted locally on the device. To re-test mediation from a
> clean state, clear the app data (Android) or uninstall and reinstall the app (iOS)
> before running again.

---

## Settings ID

The example app uses the settings ID `Yi9N3aXia` by default, configured in
`example/lib/main.dart`. To test with your own Usercentrics configuration, replace it
with your settings ID from the [Usercentrics Admin Interface](https://admin.usercentrics.eu).

You can enable and run the Consent Mediation example in this example by following the [documentation](https://usercentrics.com/docs/apps/features/consent-mediation/#enable-mediation).
---

## Learn more
## Learn More

- Check out the full [documentation](https://docs.usercentrics.com/cmp_in_app_sdk).
- Check our [website](https://usercentrics.com).
- [Usercentrics Documentation](https://docs.usercentrics.com/cmp_in_app_sdk)
- [Consent Mediation Guide](https://usercentrics.com/docs/apps/features/consent-mediation/#enable-mediation)
- [Usercentrics Website](https://usercentrics.com)
9 changes: 8 additions & 1 deletion example/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ plugins {
id "com.android.application"
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
// Uncomment to enable Firebase Analytics (required for consent mediation testing).
// Place google-services.json in example/android/app/ before building.
// See example/README.md for setup instructions.
// id "com.google.gms.google-services"
}

def localProperties = new Properties()
Expand Down Expand Up @@ -40,7 +44,7 @@ android {
}

defaultConfig {
applicationId "com.usercentrics.sdk.flutter_example"
applicationId "com.usercentrics.sdk.mediation.test"
minSdk flutter.minSdkVersion
targetSdk 34
versionCode flutterVersionCode.toInteger()
Expand All @@ -62,4 +66,7 @@ flutter {

dependencies {
implementation "androidx.multidex:multidex:2.0.1"

implementation platform('com.google.firebase:firebase-bom:33.13.0')
implementation 'com.google.firebase:firebase-analytics'
}
6 changes: 6 additions & 0 deletions example/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
android:label="Usercentrics Flutter Sample"
android:icon="@mipmap/ic_launcher"
android:name="androidx.multidex.MultiDexApplication" >

<meta-data android:name="firebase_analytics_collection_enabled" android:value="false" />
<meta-data android:name="google_analytics_default_allow_analytics_storage" android:value="false" />
<meta-data android:name="google_analytics_default_allow_ad_storage" android:value="false" />
<meta-data android:name="google_analytics_default_allow_ad_user_data" android:value="false" />
<meta-data android:name="google_analytics_default_allow_ad_personalization_signals" android:value="false" />
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
Expand Down
1 change: 1 addition & 0 deletions example/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:8.3.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.gms:google-services:4.4.4'
}
}

Expand Down
7 changes: 7 additions & 0 deletions example/ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ target 'Runner' do

flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))

# Uncomment to use a local UsercentricsUI build (requires mobile-sdk repo checked out
# at ../../../mobile-sdk/platforms/ios/UsercentricsUI relative to this file).
# pod 'UsercentricsUI', :path => '../../../mobile-sdk/platforms/ios/UsercentricsUI'

# Firebase Analytics — required for consent mediation testing.
pod 'FirebaseAnalytics'

target 'RunnerTests' do
inherit! :complete
end
Expand Down
Loading
Loading