How OkCredit Android App improves UX writing by changing strings on the fly (and you can too!)

Rashanjyot Singh
OkCredit
Published in
6 min readJul 13, 2022
Dynamic string updates on the fly, without any app releases

Foreword

⚠️ First things first! We don’t want to make any false claims, and to tell you straight off, you cannot update the strings stored as XML resources in your android app. However, we are here to tell you how we achieved that effect in OkCredit android app by using ‘Philology’, an open-source android library.

OkCredit is a digital ledger app used by millions of small business owners and their customers daily to facilitate the recording of credit/payment transactions digitally all over India.

The app supports over 11 different languages and to cater to such a diverse userbase, one key aspect is to communicate effectively. A pain point often shared by our product managers and language localization teams was that each time we wanted to experiment with strings, change/update them or make changes to translations of specific languages, we had to release a new version of the app.

Hence, we wanted to have a setup that would enable us to experiment with strings faster and update them on the fly without releasing a new version of the app.

Let’s Get Started

Like most apps, OkCredit app uses a lot of XML string resources, and an ideal implementation to set up string experimentation would be one that requires the bare minimum amount of changes in the way we conventionally fetch strings, which is using getString(...) method of the Resources class.

The android developer community is amazing and that’s what we realized yet again when we instantly found exactly what we needed. We figured out quite a few technical blogs and a couple of open-source libraries that explained the underlying mechanism well (hence, we won’t do that much herein and simply share the relevant links).

However, to build conviction that it could run flawlessly at scale, we needed to pilot the solution first-hand. After using it for numerous experiments to improve the experience for millions of our users, with this blog we wish to share:

  1. Primarily, a case study of one of the experiments at OkCredit and insights indicating the solution’s reliability.
  2. A brief technical overview of our setup for string experimentation.

a) Usecase

OkCredit app has a ledger screen for customers and suppliers wherein a merchant can record credit/payment transactions.

The texts in the above image (‘Payment’ and ‘Credit’) are localized based on the user’s language preference. Based on specific insights, we wanted to experiment with different terms across different languages to understand their impact on ‘user activation’, which we’ll soon have a look at in the upcoming sections.

b) Test variants for experiment

Our language localization team designed multiple test variants for different languages. Here’s a glimpse:

For this case study, we will focus only on the cohort of users who selected ‘English’ as their preferred language.

c) Cohort Selection & Design:

Based on metrics such as conversion rate, number of test variants, daily visitors etc., we aimed to experiment with a cohort size of ~60K users over a test duration of ~10 days to confirm if there was a significant impact.

d) Success Metrics and Results:

‘User Activation’ was the primary metric for this experiment, wherein a new user is deemed ‘activated’ given he/she completes the following steps in the app:

With an almost equal distribution of users amongst the variants, we found a significant 1.7% increase in the user activation rate for the test variant over the control variant.

Technical Overview

To achieve this, we used an open-source library, ‘Philology’, which allowed us to define a custom implementation of a data source, which would be used to fetch the updated strings. Under the hood, this mechanism works by intercepting the view inflation process to get the updated string values. The library has excellent documentation of the steps required to integrate this into a project, and hence we recommend you follow the instructions from the same.

a) Defining custom data source implementation

At its core, the setup needs an implementation of PhilologyRepositoryFactory, which can map to multiple PhilologyRepositoryinstances based on locale(s).

Each implementation of PhilologyRepository provides the updated value for the string key to be used if present, else returns null if the original value from XML string resources is to be used.

Each implementation of PhilologyRepository requires you to define your custom logic that returns the value used for a given string key. You may choose to fetch it from database(s), shared preferences, API call(s) or any other source(s) of data as you may like. In case you wish to use the original value as defined in XML, you can simply return null.

Then, all you need to do is to inject this setup into the context, and voila! you are all set to get the updated string values using the conventional Resources.getString(...) function 🥳.

b) A/B testing setup for experimentation

Moreover, our custom implementation of the data source leverages a custom in-house A/B testing setup that allows us to run experiments by selectively rolling them out to our desired cohort of users, set up control and test variants, and manage the distribution fractions amongst each variant.

c) Minor issues & a word of caution

We faced an issue while upgrading to androidx.appcompat:appcompat:1.2.0, wherein the resource interception failed. However, this was fixed via a comment addressed in the issues —

⚠️ This highlights the problem of the library not being very actively maintained and that it may cause issues sooner or later, which may require some time to fix.

🚨 Additionally, ‘Philology’ internally uses ‘ViewPump’, a library to intercept view inflation, which also seemingly isn’t actively maintained at the time of writing this.

However, based on our experience, we have found the library to be fairly stable throughout our extensive use for the past two years.

On the other hand, we recently came across another open-source library named ‘Restring’, which seems to be pretty actively maintained at the time of writing this. Also, the author of the same has been relatively maintaining an active repo of ‘ViewPump’, which extends the repo mentioned earlier. However, we haven’t evaluated it yet, but recommend you to do it if you’re starting out with this.

Conclusion

We strongly feel that the developers of these libraries and authors of several blogs online have already done a great job at explaining the nitty-gritty and to get started with implementation, we recommend you to go through the README.md file of these repositories.

We primarily wanted to share insights from an on-ground case study of ours, indicating the reliability of the solution. Now, if you are excited to run string experiments using this or in some other way, we’ve got our job done.

Thanks for making it till here and 👏 if this helped you. Feel free to reach out if you have any questions, suggestions or ideas.

--

--