Install and upgrade the SDK
The ContentFlow SDKs are versioned archives you download from this site, verify, and keep in your repository. There is no package on npm, CocoaPods, Maven or pub.dev. This page covers every platform: what each needs, how to install it, how to confirm which version you run, and how to upgrade or roll back.
- Download the archive for your platform and the release's
SHA256SUMSfile from Releases and downloads, and never install an archive whose checksum fails. - Keep the archive in a folder you commit (this page uses
vendor/) and install it from there: npm for JavaScript, React and React Native, a local Swift package, a Gradle composite build for Kotlin, a path dependency for Flutter. - React Native 0.72 to 0.78 and Expo SDK 50 to 52 need one Metro setting; 0.79+ and Expo 53+ need none.
- An upgrade is the same steps with the new archive, plus that version's Action needed notes in the release notes.
Requirements
| Platform | Package | Minimum |
|---|---|---|
| Web | contentflow-sdk-<version>.tgz (@contentflow/sdk/web, or /embed for a page without a build step) | A bundler that reads package exports, or the script tag |
| React | the same archive (@contentflow/sdk/react) | React 17 |
| React Native and Expo | the same archive (@contentflow/sdk/react-native, /expo) | React Native 0.72, Expo SDK 50; Hermes or JSC; new or legacy architecture (details) |
| Swift | contentflow-sdk-swift-<version>.zip (products ContentFlow, optional ContentFlowLocation) | iOS 15, macOS 12, tvOS 15, watchOS 8 |
| Kotlin | contentflow-sdk-kotlin-<version>.zip (modules :android or :compose, optional :location, :geofencing) | Android minSdk 24, JVM 17 |
| Flutter | contentflow-sdk-flutter-<version>.zip (contentflow_sdk) | Dart 3.5, Flutter 3.16 |
Download and verify
From Releases and downloads, save your platform's archive and that release's checksum file into one folder, then verify before installing. The downloads are public and need no account or token.
cd vendor
shasum -a 256 -c --ignore-missing SHA256SUMS-2.4.1.txt # Linux: sha256sum -c --ignore-missing
# Windows (PowerShell): Get-FileHash .\contentflow-sdk-2.4.1.tgz -Algorithm SHA256, then compare with the file
# Every line must say OK. Never install an archive that fails.
Install
Pick your platform. Each tab is the complete install; optional pieces are commented.
# 1. Install the archive.
npm install ./vendor/contentflow-sdk-2.4.1.tgz
# 2. Import the web entry point in your code:
# import { createCFClient } from '@contentflow/sdk/web';
# A page without a build step uses the script-tag build instead
# (copy package/dist/web/embed.js from the archive; see "Script tag" in the SDK guide).
# 3. Rebuild your app.# 1. Install the archive. React (17 or later) is supplied by your app.
npm install ./vendor/contentflow-sdk-2.4.1.tgz
# 2. Wrap your app in the provider:
# import { CFProvider } from '@contentflow/sdk/react';
# <CFProvider config={{ publicKey: CONTENTFLOW_SDK_KEY }}>…</CFProvider>
# 3. Rebuild your app.# 1. Install the archive and AsyncStorage (required: device id, consent, cache).
npm install ./vendor/contentflow-sdk-2.4.1.tgz
npm install @react-native-async-storage/async-storage # Expo: npx expo install @react-native-async-storage/async-storage
npm install react-native-sse # optional: live updates instead of polling
npm install @react-native-community/geolocation # optional: device location (bare)
# Expo push helper: npx expo install expo-notifications
# 2. React Native 0.72 to 0.78 / Expo SDK 50 to 52 only: in metro.config.js set
# resolver.unstable_enablePackageExports = true
# then restart Metro with a clean cache (npx react-native start --reset-cache, or npx expo start -c).
# 3. Rebuild the native app: AsyncStorage adds native code, so a JS reload is not enough.
cd ios && pod install && cd .. # bare React Native
npx react-native run-ios # or run-android; Expo: npx expo run:ios / run:android// 1. Extract contentflow-sdk-swift-2.4.1.zip into Vendor/ without changing its layout.
// 2a. Xcode project: File → Add Package Dependencies → Add Local…, pick the extracted folder,
// then add the ContentFlow library (and ContentFlowLocation only if you use device location)
// under the target's Frameworks, Libraries, and Embedded Content.
// 2b. Or in Package.swift:
dependencies: [
.package(path: "../Vendor/contentflow-sdk-swift-2.4.1"),
],
targets: [
.target(name: "App", dependencies: [
.product(name: "ContentFlow", package: "contentflow-sdk-swift-2.4.1"),
// .product(name: "ContentFlowLocation", package: "contentflow-sdk-swift-2.4.1"), // optional
]),
]
// 3. Build. A local package's identity is its folder name; keep the versioned name.// 1. Extract contentflow-sdk-kotlin-2.4.1.zip into vendor/ (it creates vendor/contentflow-sdk-kotlin).
// There is no Maven artifact: the SDK is included as a composite build.
// 2. settings.gradle.kts
includeBuild("vendor/contentflow-sdk-kotlin")
// app/build.gradle.kts
dependencies {
implementation("click.contentflow:compose") // or "click.contentflow:android" without Compose
// (the built-in campaign popup card is Compose-only)
// implementation("click.contentflow:location") // optional: device location
// implementation("click.contentflow:geofencing") // optional: on-device geofences (Play services)
}
// 3. Sync Gradle and build (minSdk 24, JVM 17).# 1. Extract contentflow-sdk-flutter-2.4.1.zip into vendor/ (it creates vendor/contentflow-sdk-flutter).
# 2. pubspec.yaml
dependencies:
contentflow_sdk:
path: vendor/contentflow-sdk-flutter
# 3. Fetch packages and build (Dart 3.5+, Flutter 3.16+):
# flutter pub getThen show your first block: Get started, step 2. React Native specifics (dependencies, Metro, Expo push) are in the React Native and Expo guide.
Check the installed version
Confirm the version your build actually contains. Every SDK also sends it on each request as X-CF-SDK-Version: <platform>/<version>.
// npm ls @contentflow/sdk → @contentflow/sdk@2.4.1
import { SDK_VERSION } from '@contentflow/sdk/web';
console.log(SDK_VERSION); // "2.4.1"# The React entry point ships in the same package as the web one.
npm ls @contentflow/sdk # @contentflow/sdk@2.4.1# The React Native entry point ships in the same package as the web one.
npm ls @contentflow/sdk # @contentflow/sdk@2.4.1import ContentFlow
print(ContentFlowSDK.version) // "2.4.1"import click.contentflow.SDK_VERSION
Log.d("CF", SDK_VERSION) // "2.4.1"import 'package:contentflow_sdk/contentflow_sdk.dart';
print(kContentFlowSdkVersion); // "2.4.1"Upgrade
- Read the Action needed notes for every version between yours and the new one in the release notes.
- Download and verify the new archive (step 1).
- Swap it in for your platform (below) and rebuild.
- Run Testing your integration again, then delete the old archive.
# Replace the tarball in vendor/, install it, rebuild.
rm vendor/contentflow-sdk-2.3.0.tgz
npm install ./vendor/contentflow-sdk-2.4.1.tgz
npm ls @contentflow/sdk # confirm @contentflow/sdk@2.4.1# Same package as the web SDK: replace the tarball, install, rebuild.
rm vendor/contentflow-sdk-2.3.0.tgz
npm install ./vendor/contentflow-sdk-2.4.1.tgz
npm ls @contentflow/sdk # confirm @contentflow/sdk@2.4.1# Replace the tarball and install it.
rm vendor/contentflow-sdk-2.3.0.tgz
npm install ./vendor/contentflow-sdk-2.4.1.tgz
# Restart Metro with a clean cache and rebuild the native app.
npx react-native start --reset-cache # Expo: npx expo start -c
npx react-native run-ios # or run-android; Expo: npx expo run:ios / run:android
# Upgrading React Native itself needs no new SDK. On 0.79+ / Expo 53+ you can drop
# the unstable_enablePackageExports line from metro.config.js.// The folder name is the package identity, so update the path AND every package: argument.
dependencies: [
.package(path: "../Vendor/contentflow-sdk-swift-2.4.1"),
],
// … .product(name: "ContentFlow", package: "contentflow-sdk-swift-2.4.1")
// Xcode project: remove the old local package, Add Local… the new folder,
// then File → Packages → Reset Package Caches, and build.// Replace vendor/contentflow-sdk-kotlin with the new extraction (the path stays the same),
// then refresh the composite build:
// ./gradlew --refresh-dependencies build
// settings.gradle.kts and app/build.gradle.kts need no change.
includeBuild("vendor/contentflow-sdk-kotlin")# Replace vendor/contentflow-sdk-flutter with the new extraction (the path stays the same),
# then fetch packages and rebuild:
# flutter pub get
dependencies:
contentflow_sdk:
path: vendor/contentflow-sdk-flutterRoll back
Rolling back is an upgrade in reverse: install the previous archive with the same steps for your platform, and revert any Action needed changes you made for the newer version. This site hosts the current and the previous release; older archives are not served here any more, so keep the archive you shipped in your repository (or your own artifact store) until you no longer need it. Releases and downloads still lists the checksum of every release, so an archive you kept can be verified.
When it doesn't work
| What you see | Why, and the fix |
|---|---|
A checksum line says FAILED | The download is incomplete or not the published file. Download it again from Releases and downloads; never install it. |
Unable to resolve module @contentflow/sdk/react-native | Metro is not reading package exports: on React Native 0.72 to 0.78 or Expo SDK 50 to 52 turn on unstable_enablePackageExports; on 0.79+ make sure nothing sets it to false. Restart Metro with a clean cache. On 0.71 or earlier, upgrade React Native. |
| React Native app crashes on start after installing | AsyncStorage adds native code: rebuild the native app (pod install, then run the app), a JavaScript reload is not enough. |
| Xcode still builds the old Swift SDK | The package identity is the folder name: update the path and every package: argument, remove the old local package, then File → Packages → Reset Package Caches. |
| Gradle still resolves the old Kotlin SDK | Run ./gradlew --refresh-dependencies build after replacing vendor/contentflow-sdk-kotlin. |
| The version check shows the old number | The build still contains the old archive: clean the build (and the bundler cache), then rebuild. |
Next
- Show your first block: start the client, set consent, read a block.
- Release notes: what changed in each version and what to do when you upgrade.