Page MenuHomePhabricator

[Epic] Upgrade fundraising configuration to support A/B testing
Closed, ResolvedPublic

Description

It would be great if we could build on the current structure of our campaign configurations to be able to support A/B testing (of different verbiage, etc).

Here is our current way of encoding campaign assets:

assets: {
  en: {
    text: "...",
    actions: { ... }
  }
}

And here is the new proposed style:
When not running an A/B test:

assets: {
  en: [
    {
      text: "...",
      actions: { ... }
    }
  ]
}

...And when running an A/B test:

assets: {
  en: [
    {
      weight: 0.5,
      id: "verbiageA",
      text: "This is verbiage A!",
      actions: { ... }
    },
    {
      weight: 0.5,
      id: "verbiageB",
      text: "This is verbiage B!",
      actions: { ... }
    },
  ]
}
  • Notice how, when not running an A/B test, the structure is almost the same, except it's an array. (and the new weight and id parameters are optional)
  • And when running an A/B test, the weight and id parameters are used, and you could have an arbitrary number of verbiage objects - not just two, which will be chosen on the client side, based on the weight.
  • On the client side, the app will randomly put the current user (based on app_install_id) into one of the asset buckets, taking the weights into account.
  • This will necessitate bumping the version of the top-level campaign object to 2 (currently 1). Note that different versions of campaign objects can coexist in the same top-level array of objects, so we'll be able to make lists of campaigns that target both new versions of apps, as well as older versions that don't support a/b testing.
  • For tracking impressions, we could use the top-level campaign id (as we do currently), and append the newly-added id of the a/b verbiage that gets chosen. So it will become something like BR_2025_03_verbiageA / BR_2025_03_verbiageB.
Effort estimate

Large task for a single developer (per team).

Details

Other Assignee
Tsevener

Event Timeline

Seddon updated Other Assignee, added: Tsevener.

Hey @Seddon - why have these tasks become priority right now? I don't remember us talking about this as a team.

I didn't realize this was a spike! I thought it was the implementation task. @Dbrant No concerns from me re: this being picked up right now.

@Dbrant around how much engineering time would be needed to achieve this?

@Dbrant around how much engineering time would be needed to achieve this?

I'd estimate this to be a Large task for a single developer (per team).

@Dbrant Could you please create necessary tasks for implementing this on Android and iOS? It's something we could aim to do before Big English 2025

Dbrant renamed this task from [spike] Upgrade fundraising configuration to support A/B testing to [Epic] Upgrade fundraising configuration to support A/B testing.Jun 27 2025, 12:38 PM
Dbrant updated the task description. (Show Details)
Dbrant removed the point value 1 for this task.

Hi everyone, just subscribed to this task to follow up on the A/B testing feature. Do you have a rough estimate when this might be ready? Echoing @HNordeenWMF , we're thinking of running pre-test campaigns during Big English using this. Thanks in advance!

@Dbrant I've been working on making these changes in a branch, so far it's looking good. A couple of thoughts I had:

  1. The randomly chosen asset is changing whenever the config is fetched again, so upon Explore feed refresh and relaunching the app. Is there a hard requirement that it must remain static for the lifetime of the app install? As long as we log the correct identifier, we will know which verbiage they saw. If it's a hard requirement, I can look into adding a seed like you did for Android.
  2. Just note I think we'll have to make sure the wmf_source query item in the asset > action > url is appending the asset variant ID as well.
  1. The randomly chosen asset is changing whenever the config is fetched again, so upon Explore feed refresh and relaunching the app. Is there a hard requirement that it must remain static for the lifetime of the app install? As long as we log the correct identifier, we will know which verbiage they saw. If it's a hard requirement, I can look into adding a seed like you did for Android.

Not a hard requirement, but would be ideal if the asset is chosen randomly, yet deterministically per app_install_id.
But if Swift doesn't provide a built-in way to seed your PRNG (😲), it's probably OK to re-select the asset randomly every time it's fetched, as long as the corresponding id is passed on to analytics.

@SNowick_WMF any perspectives on the assigment questions?

Hi - As long as the campaign_id is appended with the id of the a/b verbiage as described in task I will be able to see all events associated with each test, this looks good to me. Devs if there are any potential pitfalls I might be missing lmk, thanks.

Data Validation from app_donor_experience as of 2025-09-16:

beta passed iOS and Android