LG-8190: A/B Testing of Acuant SDK Upgrade#7392
Conversation
changelog: Internal, A/B Testing, Acuant SDK Upgrade A/B Test Implementation
changelog: Internal, AB Testing, Acuant SDK Upgrade AB Testing
app/services/analytics_events.rb
Outdated
| # @param [String] version The version of the Acuant SDK that was loaded | ||
| # An A/B test for loading the old vs new version of the Acuant SDK. | ||
| # If this analytics call is not made at all, then the test isn't enabled. | ||
| def idv_acuant_sdk_upgrade_a_b_test( |
There was a problem hiding this comment.
based on the wording of the JIRA, I think that it might be good to add AB test attributes to the existing idv_doc_auth_submitted_image_upload_vendor or something, so that we could easily correlate A/B test bucket with results
having a separate event like this to proactively log which bucket is good too in case users don't make it as far as submissions
There was a problem hiding this comment.
Yeah we need to know at SDK load time (ie before any submission or even attempts). Should we do both, keep the new event and amend the upload vendor event?
There was a problem hiding this comment.
yeah seems like it would be useful to have the info at both events
There was a problem hiding this comment.
The way that flow_path is tracked across events during document capture could serve as good prior art to follow:
identity-idp/app/javascript/packs/document-capture.tsx
Lines 69 to 72 in 9657a83
Co-authored-by: Zach Margolis <zachmargolis@users.noreply.github.com>
changelog: Internal, AB Testing, Acuant SDK Upgrade AB Testing
changelog: Internal, AB Testing, Acuant SDK Upgrade AB Testing
changelog: Internal, AB Testing, Acuant SDK AB Testing
changelog: Internal, AB Testing, Acuant SDK Upgrade AB Testing
Co-authored-by: Zach Margolis <zachmargolis@users.noreply.github.com>
| @@ -0,0 +1,120 @@ | |||
| import { useContext } from 'react'; | |||
There was a problem hiding this comment.
Since this is a new file and all new code should be TypeScript, can we make this file .tsx?
| sdkSrc = '/acuant/11.7.0/AcuantJavascriptWebSdk.min.js', | ||
| cameraSrc = '/acuant/11.7.0/AcuantCamera.min.js', |
There was a problem hiding this comment.
Are we planning to keep this code pattern around for a while?
If so, and if we plan to hard-code the version sources, I'd suggest getting rid of the prop altogether, since it's misleading to imply that it can be customized if the logic of the component will ignore the value depending on the A/B testing value.
Alternatively, we could adapt the component to receive the two sets of sources.
There was a problem hiding this comment.
Are we planning to keep this code pattern around for a while?
My understanding is that we wanted to let this run for a week, maybe two. However I think we should have clarification. If we are going to AB test upgrades in the future (and why not?) then you are right, we should change some if these assumptions. Additionally, we'd probably want to set the old/new version numbers in the identitystore config
There was a problem hiding this comment.
@aduth After toying around with this a bit more, it seems that the sdkSrc and cameraSrc props were introduced specifically for the tests so that an error isn't thrown when these resources don't load during a frontend test. Here is an example.
I've gone ahead and pushed some changes, whereby a source prop is passed in explicitly, that's what gets used no matter what (for now only tests use it this way). Otherwise, we kick it to the ab test context to determine which version/path to specify.
I've also added some constants to make this a little cleaner.
lmk what you think
changelog: Internal, AB Testing, Acuant SDK Upgrade AB Testing
-- What AD suggested piggy-backing on the document-capture.tsx pack's version of trackEvent, which wraps the plain trackEvent in order to add its own extra data. We now use this for adding information about the sdk upgrade ab testing. changelog: Internal, AB Testing, Acuant SDK Upgrade AB Testing
changelog: Internal, AB Testing, Acuant SDK Upgrade AB Testing
changelog: Internal, AB Testing, Acuant SDK Upgrade AB Testing
61cfa6b to
82b3bef
Compare
-- What We need the cameraSrc and sdkSrc props on the Acuant context, because tests provide about:blank so that the loading of the scripts does not throw errors (and success can be simulated on frontend). This commit provides a mechanism by which these props are null by default, but if there is a value present they will be used above any other consideration. If null, we kick it to the ab test and then to determine which path(s) to use. changelog: Internal, AB Testing, Acuant SDK Upgrade AB Testing
| ...payload, | ||
| flow_path: flowPath, | ||
| acuant_sdk_upgrade_a_b_testing_enabled: acuantSdkUpgradeABTestingEnabled, | ||
| use_newer_sdk: useNewerSdk, |
There was a problem hiding this comment.
Should we consider populating the context with the Acuant version, and using that as part of the analytics event, as well as in place of the constants in acuant-sdk-upgrade-a-b-test.tsx? Or, maybe we don't even need an extra context provider, and can just use AcuantContext in the way it was designed to receive the sdkSrc?
(Short on time to elaborate at the moment, but will follow-up with more detail on what I had in mind)
There was a problem hiding this comment.
What I was thinking is maybe the frontend would provide an SDK version if and only if A/B testing is enabled, and then that version (if given) is used to derive a source string to be given directly to the existing AcuantContext, so that we don't need a new context, and so that AcuantContext wouldn't require many (or any) additional changes.
interface AppRootData {
// ...
acuantVersion?: string;
}
const {
// ...
acuantVersion,
} = appRoot.dataset;
const isAcuantSDKUpgradeABTestingEnabled = typeof acuantVersion === 'string';
const trackEvent: typeof baseTrackEvent = (event, payload) => {
// ...
return baseTrackEvent(event, {
...payload,
// ...
acuant_sdk_upgrade_a_b_testing_enabled: isAcuantSDKUpgradeABTestingEnabled,
acuant_version: acuantVersion,
});
};
const App = composeComponents(
// ...
[
AcuantContextProvider,
{
// ...
sdkSrc: acuantVersion && `/acuant/${acuantVersion}/AcuantJavascriptWebSdk.min.js`,There was a problem hiding this comment.
Makes sense. The one amendment I would suggest is to also have the actual acuant_sdk_upgrade_a_b_testing_enabled value also be on the AppRoot, because this way we can specify the acuant version to use regardless of the AB test (ie, let's always specify a version to use). Otherwise we would have hard coded values for the version still present in the acuant context
There was a problem hiding this comment.
I just pushed 6c1a5e1 which should implement most of your suggestions, along with some minor differences.
To me the outstanding issues are -- as I mentioned in the commit message -- whether/where to store the version numbers as globally accessible values, and whether or not we track an event for when the acuant sdk successfully loads or not.
There was a problem hiding this comment.
whether/where to store the version numbers as globally accessible values
Do we need to access them anywhere else? If not, I don't think we'd need to do anything.
If we do, we can probably expose / access AcuantConfig.acuantVersion which would give us the version detail after the script is loaded.
whether or not we track an event for when the acuant sdk successfully loads or not.
What questions are we trying to answer with such an event? Are we concerned that the scripts might not load correctly?
Could we indirectly infer that from this event?
identity-idp/app/javascript/packages/document-capture/context/acuant.tsx
Lines 253 to 256 in 8c40e37
We could add the AcuantConfig.acuantVersion in there if we wanted?
There was a problem hiding this comment.
Could we indirectly infer that from this event?
Yeah for sure, since we wrapped the default trackEvent in document capture and add all that extra information (in the pack). I am not so savvy on Cloudwatch queries so I don't know how much of a pain that is, however. If you think it's GTG let's just roll with it.
Do we need to access them anywhere else?
I am only thinking of the version numbers present in the default paths of the AcuantContext provider here. All other version information is defined on the Rails side now.
But again, if you think this is GTG for the moment let's push on
There was a problem hiding this comment.
Oh, right, I forgot we added it in the base trackEvent, so it should be easy to distinguish in CloudWatch by e.g. filter properties.event_properties.acuant_version = '11.7.0', etc.
-- What As suggested in a thread by @aduth [#7392 (comment)] we probably don't need all the overhead of a new React Context for dealing with the Acuant version a/b testing. Instead, we can surmise what the camera and sdk routes should be from the AppRoot values and simply pass these to the AcuantContextProvider. This commit represents deletions, modifications, and test updates that attempt to implement this suggestion. As I see it, there are still two open questions that are not deal breakers for finishing this work in the immediate term: 1. We declare the src routes as default prop values in the Acuant context (React), but also specify these versions in the document capture step file (ruby). Should we specify the new and old versions as globals somewhere (IdentityConfig store)? 2. Do we have a trackEvent call for when the acuant SDK has loaded or attempts to load? If not, should we add one? (I'm thinking about the a/b test information being present at load time vs capture time vs submission time) changelog: Internal, AB Testing, Acuant SDK Upgrade Testing
changelog: Internal, AB Testing, Acuant SDK Upgrade AB Testing
changelog: Internal, AB Testing, Acuant SDK Upgrade AB Testing
solipet
left a comment
There was a problem hiding this comment.
LGTM. Only comment I had was in regards to the default config.
config/application.yml.default
Outdated
| idv_min_age_years: 13 | ||
| idv_native_camera_a_b_testing_enabled: false | ||
| idv_native_camera_a_b_testing_percent: 10 | ||
| idv_acuant_sdk_upgrade_a_b_testing_enabled: true |
There was a problem hiding this comment.
Do we really want this enabled by default? I would expect a test to be disabled by default and explicitly enabled per environment.
There was a problem hiding this comment.
I'll switch back and you can walk me through the typical process
changelog: Internal, AB Testing, Acuant SDK Upgrade AB Testing
🎫 Ticket
LG-8190
🛠 Summary of changes
We want to A/B test the upgrade of the Acuant SDK from 11.7.0 to 11.7.1 (50/50 each) for a bit and see if we notice any key differences.
This PR implements an AbTests constant and bucket instance for the specific case. We also have implemented the necessary changes on the React side (mostly context object code) and associated tests.
📜 Testing Plan
Run through the following two scenarios:
Scenario 1
acuant_versionanduser_newer_sdkproperties be 11.7.0 andfalse, respectivelyScenario 2
acuant_versionanduser_newer_sdkproperties be 11.7.1 andtrue, respectively