Social Bet Sharing
Social bet sharing enables users to share pending and resulted bets through their device's native sharing functionality with other apps including messaging and social media apps.
Product Overview
When a bet is shared, an image representing that bet is generated and, if the bet would still be bettable by others at the time it is shared, a unique link is also generated. If the link is opened by another user, the bet details are automatically loaded into the Betslip and opened for the user to enter the amount they wish to bet and submit it.
Links / Briefings
- #product-social-bet-sharing on Slack
- Miro
- Discovery workshop (recording)
Designs
Dependencies
react-native-share
react-native-share
improves the default sharing capability of the react-native
. In particular it enabled us to share both an image and the shared bet url at the same time, across both platforms in a consistent API.
react-native-view-shot
react-native-view-shot
is the library that allows us to generate an image from standard react-native
components. Once we have rendered the SharePreview
for the selected bet, we can turn it into an image that matches exactly what the user sees on their screen, which keeps it dynamic and configurable before they press the share button.
Component Model
When looking at the designs, there were many UI elements that were shared in different areas of the bet image but used different data sources (e.g. a selection
instead of a leg
) or in a different location (e.g. a single sports bet looks very similar to a sports bet leg of a multi bet).
To make the most of the similarities in the designs we designed the component architecture to follow a container/presentational component model (often called "smart" and "dumb" components. In this arrangement, it's common to have the leaves of the component tree with very little logic in them, simply accepting props of primitive data and laying out and styling the component. These are the presentational components. Wrapping these presentational components are the container components that are responsible for collecting the data and choosing which more primitive values to pass into the presentational components.
The reuse is enabled by having different container components for different variations of bets that use the same underlying presentational components.
Styling
A theme object called betSharing
was introduced to handle the styling variables of the social bet sharing module. Generally, this object is limited to colours and font variables, while layout and spacing is handled by inline BoxProps
throughout the component structure as there is no variance in how the preview lay out between the different brands.
Testing
Components and functions are tested can be tested with Jest. Snapshot testing is minimally used with the team deciding to prefer explicit assertions on the data appearing in the output instead, leading to fewer breaking tests as the designs evolved during development.
Implementation
Share bet link
The shared bet link has the following structure:
https://{BRAND_WEBSITE}/share-bet/{SHARED_BET_ID}
The BRAND_WEBSITE
is configured in the app config while the SHARED_BET_ID
is generated from the transaction_id
of the selected pending bet using the CreateSharedBet
handler of the bet-share
api.
There has been some discussion around shortening the url, either through smarter SHARED_BET_ID
generation or through the use of an external URL shortener, but this does not form part of the initial release at this time. You can follow the discussion here.
When the link is opened, we extract the SHARED_BET_ID
from the URL passed to the app and forward it onto the betslip-utils
to collect and generate the relevant bet slip data before opening the Betslip drawer for the user.
Client side generation
When planning the delivery of this feature, a technical decision was made to generate the images on the user's device rather than generating them in the backend and just serving them through the app. There were multiple factors that went into this decision, but the main deciding factors were:
- The existing availability of required data
- The performance characteristics and "smoothness" of having everything local to the device
- The ability to add extra UX "flair", such as animating transitions when inputs were changed.
You can see the full table used in the decision making process here.
Sharing an image
We did investigate using social previews instead of sharing images directly. This option was not pursued as the social previews are often quite restrictive on size and the dynamic nature of the bet structures does not lend itself well to this type of constraint. It's also entirely up to the app the bet is shared with as to how and whether it even uses the social previews. The final consideration was that in the case of a resulted bet, there isn't a relevant URL that can be generated in order to see the social preview.
Overall, it was decided that we would rather have the control on our end and generate and share the image directly from the app.
File Structure
- Components:
app/components/bet-sharing/
- Hooks:
app/hooks/bet-sharing/
- Utils:
app/utils/bet-sharing/