Skip to content

refactor(rokt): move Rokt API out of core into the Rokt/Payments kits - #49

Merged
denischilik merged 4 commits into
mainfrom
feat/rokt-api-into-kit
Jul 28, 2026
Merged

refactor(rokt): move Rokt API out of core into the Rokt/Payments kits#49
denischilik merged 4 commits into
mainfrom
feat/rokt-api-into-kit

Conversation

@denischilik

@denischilik denischilik commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Background

Today the Rokt managed contract lives in the core mParticle.Maui.Sdk
package: the RoktApi type, all RoktEvent subtypes, RoktConfig,
RoktEmbeddedView, and the MParticleSDK.Rokt accessor. It was added there in
#4 ("Refactor to single SDK with common API interface") as a side effect of the
single‑SDK consolidation, not as a deliberate core API decision.

This is architecturally wrong: the core mParticle package should not expose any
Rokt surface
. Rokt is an optional integration and should only appear when its
kit is referenced — the same way it works natively and in the Flutter/React
Native wrappers.

What Has Changed

  • Core (mParticle.Maui.Sdk) — removed the entire Rokt managed contract:
    RoktApi, RoktEvent (+ ~20 subtypes), RoktConfig, RoktColorMode,
    RoktEmbeddedView, MParticleSDK.Rokt, both platform RoktApiWrappers, both
    RoktEmbeddedViewHandlers, the NoOpRoktApiWrapper, and the Rokt converters in
    Utils.cs. Core no longer knows about Rokt.
  • Rokt kit (mParticle.Maui.Kits.Rokt) — now owns the Rokt contract. The
    accessor is a C# 14 extension property on MParticleSDK, so
    MParticle.Instance.Rokt only compiles when this package is referenced. The
    platform RoktApi implementations reach the native Rokt through the core's
    public generated bindings (iOSBinding / AndroidBinding) via the existing
    ProjectReference.
  • Payments kit (mParticle.Maui.Kits.Rokt.Payments)SelectShoppableAds
    moves here as an extension method on RoktApi, since it depends on a
    natively registered payment extension. It appears on MParticle.Instance.Rokt
    only when the Payments package is referenced.
  • Samples — import mParticle.MAUI.Rokt (and .Payments) and resolve
    RoktEmbeddedView from the kit assembly (XAML clr-namespace updated).
  • MParticleOptions.LogLevel fix (both platforms) — the managed LogLevel
    was never forwarded to the native builders, so the native SDKs stayed at their
    default level and VERBOSE diagnostics (including batch‑upload logs) were never
    emitted. Android now maps and calls builder.LogLevel(...); iOS exposes
    logLevel on the binding and assigns mpOptions.LogLevel. This was required to
    verify event/upload/Rokt behaviour during runtime testing below.

Resulting layering:

Package Public surface
mParticle.Maui.Sdk (core) mParticle only — no Rokt
mParticle.Maui.Kits.Rokt MParticle.Instance.Rokt + SelectPlacements/Events/GlobalEvents
mParticle.Maui.Kits.Rokt.Payments Rokt.SelectShoppableAds(...)

The core assembly still contains the low‑level generated native bindings
(iOSBinding/AndroidBinding) for Rokt. That is unavoidable plumbing: the
Apple core SDK physically ships Rokt, so its binding is always generated in
core. This PR only removes the product‑level managed API, which is what
matters for consumers.

Why this path (and why it isn't wasted work)

We deliberately base this on main (native mParticle 5.x, where Rokt still
lives in android-core) rather than on the native‑SDK‑6 branch. This is a pure
MAUI‑layer API redesign and is independent of the native version: core keeps
binding native Rokt from android-core, and the kit reaches it through its
ProjectReference to core.

The key point: had we gone straight to the native SDK 6 upgrade, we would have
been forced to do this exact relocation anyway.
In native Android 6.0 Rokt was
removed from android-core and moved into android-rokt-kit, so the core MAUI
binding can no longer expose Rokt at all (the old com.mparticle.Rokt import
stops resolving). On the native‑6 branch we worked around that with
provider‑hooks + a no‑op in core, but the managed RoktApi contract was left in
core purely for backwards compatibility — i.e. core advertised a Rokt API it
could no longer back natively.

So the correct end‑state is the same regardless of the native bump: the Rokt
managed API belongs in the kit.
Doing it now, decoupled from the native
upgrade, means:

  • the native‑SDK‑6 branch no longer needs any Rokt provider‑hook / no‑op
    scaffolding in core — the kit already owns everything;
  • the API change is reviewed on its own, without the noise of the native bump;
  • consumers who only reference core can no longer accidentally depend on Rokt.

Testing

Build validation

  • Built green end‑to‑end on Android: core, Rokt kit, Payments kit and the
    Rokt SampleApp, plus NuGet pack of core.
  • iOS is not buildable locally (no maui-ios workload) — relies on CI. The iOS
    code is structurally symmetric to Android and uses the same core iOSBinding
    types already exercised by core/samples.

Package‑isolation check (Rokt vs Payments)

Verified the new layering actually enforces the split by temporarily referencing
only mParticle.Maui.Kits.Rokt from the Rokt SampleApp (Payments removed):

  • Compilation fails exactly on the Payments‑only surface —
    RoktPaymentExtension.Register(...) and RoktApi.SelectShoppableAds(...)
    confirming Shoppable Ads is exclusive to the Payments kit.
  • After commenting out that Payments‑only code, the Android build is green and
    the app runs normally, confirming the base Rokt kit is self‑contained.
  • Confirmed Payments adds nothing to the Android artifact set over the base Rokt
    kit (its native side is iOS‑only), so the two references are equivalent on
    Android.

Runtime validation (Android emulator, Production workspace, LogLevel=VERBOSE)

  • Core SampleApp: Initialize → identity resolves → Log Basic Events
    batches upload (HTTP 202), verified via VERBOSE logcat (the LogLevel fix above
    is what makes these logs visible).
  • Rokt SampleApp (base mParticle.Maui.Kits.Rokt only): Initialize → Rokt kit
    registers → Show Rokt Overlay launches the native
    com.rokt.roktsdk.ui.overlay.RoktModalActivity, the experience response is
    parsed, and the placement renders (Layout ready, Rokt overlay placement loaded, RoktPlacementInteractive). No “Rokt Kit is not available”.

Screenshots/Video

Verified locally: the native Rokt overlay renders on Android with only the
base mParticle.Maui.Kits.Rokt kit referenced (Payments removed) — a Rokt
placement (“Purchase complete… You've unlocked 60% off…”, “Powered by Rokt”)
displayed inside RoktModalActivity.

Checklist

  • I have performed a self-review of my own code.
  • I have made corresponding changes to the documentation.
  • I have added tests that prove my fix is effective or that my feature works.
  • I have tested this locally.

Additional Notes

  • Breaking change: removing Rokt from the core public API warrants a major
    version bump at release time. Versions are intentionally left untouched on this
    branch.

Remove the Rokt managed contract from the core mParticle.Maui.Sdk package:
RoktApi, RoktEvent (+ subtypes), RoktConfig, RoktColorMode, RoktEmbeddedView,
the MParticleSDK.Rokt accessor, the platform wrappers and the no-op. The Rokt
surface now lives entirely in mParticle.Maui.Kits.Rokt and is exposed via a
C# 14 extension property, so MParticle.Instance.Rokt only exists when the Rokt
kit is referenced.

SelectShoppableAds moves further out into mParticle.Maui.Kits.Rokt.Payments as
an extension method on RoktApi, since it requires a natively registered payment
extension.

The core assembly still contains the low-level generated native Rokt bindings
(iOSBinding/AndroidBinding); those are plumbing mirroring the Apple/Android
native SDKs and cannot be removed on iOS.

Samples updated to import mParticle.MAUI.Rokt (+ Payments) and to resolve
RoktEmbeddedView from the kit assembly.
@denischilik
denischilik requested a review from a team as a code owner July 27, 2026 15:41
@cursor

cursor Bot commented Jul 27, 2026

Copy link
Copy Markdown

PR Summary

High Risk
Removing Rokt from the core package is a breaking public API change for any app that referenced core-only Rokt types; kit layering and extension-based access need correct package references at compile time.

Overview
Breaking: Rokt is no longer part of mParticle.Maui.Sdk. The managed contract (RoktApi, events, RoktEmbeddedView, platform wrappers) moves into mParticle.Maui.Kits.Rokt, exposed via a C# extension so MParticle.Instance.Rokt only compiles when the kit is referenced. SelectShoppableAds is removed from core/RoktApi and lives as an extension on mParticle.Maui.Kits.Rokt.Payments. Samples and README now import the kit namespace and resolve RoktEmbeddedView from the kit assembly.

Core also forwards MParticleOptions.LogLevel to native Android (builder.LogLevel) and iOS (mpOptions.LogLevel / post-init assignment), with binding updates for MPILogLevel on options.

CI workflows bump Xcode 26.0 → 26.2 and pin MAUI workload install to 10.0.103 instead of --skip-manifest-update.

Reviewed by Cursor Bugbot for commit 857e8a9. Bugbot is set up for automated code reviews on this repo. Configure here.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit c55493d. Configure here.

Comment thread Kits/rokt/Sdk/MParticle.Maui.Rokt/RoktExtensions.cs
The GitHub macOS runner no longer ships the iOS 26.0 platform, so the default
`dotnet workload install maui` (Microsoft.iOS.Sdk 26.0.11017) fails the iOS
binding build with "iOS 26.0 is not installed". Pin Xcode to 26.2 and the MAUI
workload set to 10.0.103 (Microsoft.NET.Sdk.iOS 26.2.x), which are mutually
compatible on the current runner image. Mirrors the fix already applied on the
native-sdk-6 branch.
SelectShoppableAds ignored its receiver and reached for the global
MParticle.SharedInstance.Rokt, so it never emitted the SDK-not-initialized
warning that the sibling RoktApi methods do. Add an internal NativeHandle
hook on RoktApi (exposed to the Payments kit via InternalsVisibleTo) so the
Payments extension dispatches through the receiver and mirrors the init
semantics on both platforms. Public API is unchanged.

Also fix the base Rokt kit README, which still listed SelectShoppableAds
even though it now ships only in the Payments kit.
The managed MParticleOptions.LogLevel was never mapped to the native
builders, so both platforms stayed at their default log level and
VERBOSE diagnostics (including batch upload logs) were never emitted.

- Android: add ConvertToMpLogLevel and call builder.LogLevel(...) in
  ConvertToMpOptions.
- iOS: expose logLevel on the MParticleOptions binding and assign
  mpOptions.LogLevel in ConvertToMpOptions.
@denischilik
denischilik merged commit baec80f into main Jul 28, 2026
4 checks passed
@denischilik
denischilik deleted the feat/rokt-api-into-kit branch July 28, 2026 15:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants