Advanced Concepts
Getting Tipser ids
To run Tipser Elements components you will need to pass
productId
orcollectionId
. To getproductId
, log in to app.tipser.com using your publisher's account, find a product in "Insert Products" section, click on the "<>" sign and copy it'sproductId
.
To curate a collection click "+" sign on a product tile and type the name of the collection. Then click "add". Your product is added to the collection. When all the products are added to the collection, click "<" on the right side of the site and then "<>" to copy the thecollectionId
.
Publisher data
In order to associate a piece of data owned by the publisher with an order item in Tipser, you can use a concept called posData
. A posData
is an arbitrary string that can be used to store additional information (e.g. session id, user id in your system, etc) attached to order in Tipser's database.
After the transaction is finalized, the string passed as posData
will be available back in the response from the Commissions API that can be consumed by your backend code (e.g. reporting systems).
Because
posData
is treated as a string in the Tipser system, then if you need to store a structured data (a common use case), please callJSON.stringify()
function on a JS object before passing it to Tipser (see: the examples below) and parse it back to JS object when receiving it back.
Setting up posData for the upcoming add to carts
There are two ways to setup posData
. All the upcoming add to cart requests will use that posData
value but this will not affect the posData for the items already added to the cart.
Option 1: As a global configuration setting that is passed to Elements/SDK initialization (good for static data, like the release number):
const tipserConfig = { posData: "release_2.1.5" };
Option 2: By dynamically updating the elements config (useful for
the data that is not yet available at the time of initialization):
const someData = JSON.stringify({sessionId: "5fa01be88b51", userId: "5fa01bfd3be2"});
const elementsConfigWithPosData = {...baseElementsConfig, posData: someData};
return <TipserElementsProvider config={elementsConfigWithPosData}>
...
</TipserElementsProvider>
Setting up posData for the existing items in the cart
In case the pos data needs to be updated for the items already in the cart, use the updatePosData
internal functions.
Basic example:
const PosDataUpdater = () => {
const { updatePosData } = useInternalFunctions();
const onClick = () => {
updatePosData('pos data for all items in the cart');
};
return <button onClick={onClick}>Update pos data</button>;
};
The above call will set or update the posData for all the items currently in the cart.
Advanced example:
const PosDataUpdater = () => {
const { updatePosData } = useInternalFunctions();
const onClick = () => {
updatePosData({ ['603fc1f55d24f81b603fa44c_603fc1f55d24f81b603fa44c']: 'product-specific pos data' });
};
return <button onClick={onClick}>Update pos data</button>;
};
The above call will set or update the posData the specific item in the cart, leaving the posData of the remaining items intact.
Warning: for performance reasons, the number of characters in
posData
is limited to 4000. Longer strings will be truncated down to 4000 characters.
Checkout submit functions
You can access the checkout context and create custom functions for submitting delivery and billing address forms as well as Stripe payment details.
To do that, use useCheckoutContext
hook:
const CustomSubmitButton = () => {
const checkoutContext = useCheckoutContext();
const handleClick = useCallback(() => {
// for delivery addres submition use:
checkoutContext.addresses.deliveryAddressForm.submit()
// for billing address submition use:
checkoutContext.addresses.billingAddressForm.submit();
// for payment submition use:
checkoutContext.payment.paymentForm.submit();
}, [checkoutContext]);
return <button onClick={handleClick}>Submit delivery address</button>
}
Server side rendering
To render Tipser Elements components on the server side, you can choose between two methods:
- Basic, in which you need to provide the
id
s of the Tipser Elements components that are used on the website. - Smart, where you don't need to know the
id
s, but there would be two subsequent renders. In the first one, 'dry run', we collect information about components used on the website and the proper rendering, that uses the previously collected data.
Server-side rendering takes place in several steps:
-
building a state containing the data needed for rendering
-
passing the state to the
SsrTipserElementsProvider
-
rendering the application
-
sending the same state to the browser and passing it back to the
SsrTipserElementsProvider
on the client side.
Basic method
In the basic method, you should use the StateBuilder
class to build the state. Start with creating its instances (which can be global):
import { StateBuilder } from '@tipser/tipser-elements';
const stateBuilder = new StateBuilder(POS_ID);
Then, while handling a specific request, use the stateBuilder.buildState
method, passing an object containing information about which elements are placed on the website, i.e. what products (PRODUCT_IDS), collections (COLLECTION_IDS) and whether there is the shop component (IS_SHOP_ON_PAGE).
stateBuilder.buildState({
productIds: PRODUCT_IDS,
collectionIds: COLLECTION_IDS,
shouldFetchStore: IS_SHOP_ON_PAGE,
})
This method returns a promise in which the ready state will be available, which should then be passed to SsrTipserElementsProvider
:
stateBuilder.buildState({
productIds: dataToFetch.productIds,
collectionIds: dataToFetch.collectionIds,
shouldFetchStore: dataToFetch.shouldFetchStore
}).then((initialState) => {
const markup = renderToString(
<TipserElementsProvider posId={POS_ID}>
<SsrTipserElementsProvider initialState={initialState}>
<App/>
</SsrTipserElementsProvider>
</TipserElementsProvider>
);
...
});
The initialState
should then be transferred to the browser. For this purpose, it can be assigned to the global window object and placed in the returned html document:
<script>window.TIPSER_STATE = ${JSON.stringify(initialState)}</script>
On the client side, use window.TIPSER_STATE
as the initialState
of SsrTipserElementsProvider
:
<TipserElementsProvider posId={POS_ID}>
<SsrTipserElementsProvider initialState={window.TIPSER_STATE}>
<App/>
</SsrTipserElementsProvider>
</TipserElementsProvider>
That's all! The complete example is available here.
Smart method
In the smart version, the ComponentsStateSsrManager
class should be used to build the state. For this purpose, you should create an instance of this class, which cannot be global, i.e. a new instance should be created for each request:
const componentsStateSsrManager = new ComponentsStateSsrManager(POS_ID);
Then perform the first rendering that will collect information about the components on the page:
const componentsStateSsrManager = new ComponentsStateSsrManager(POS_ID, 'prod')
const toRender = (
<TipserElementsProvider posId={POS_ID}>
<SsrTipserElementsProvider componentsStateManager={componentsStateSsrManager}>
<App/>
</SsrTipserElementsProvider>
</TipserElementsProvider>
);
//first render
renderToString(toRender);
Next, use the buildState
method available on the components instance of StateSsrManager
, which returns a promise:
const componentsStateSsrManager = new ComponentsStateSsrManager(POS_ID)
const toRender = (
<TipserElementsProvider posId={POS_ID}>
<SsrTipserElementsProvider componentsStateManager={componentsStateSsrManager}>
<App/>
</SsrTipserElementsProvider>
</TipserElementsProvider>
);
//first render
renderToString(toRender);
componentsStateSsrManager.buildState().then(() => {
//second render
const markup = renderToString(toRender);
...
});
In this case, you no longer need to manually pass the state to the SsrTipserElementsProvider
, it is done automatically. The last step is to transfer the state to the browser in a similar way as it was done in the basic version, but this time the state should be extracted from componentsStateSsrManager
using the getState
method:
<script>window.TIPSER_STATE = ${JSON.stringify(componentsStateSsrManager.getState())}</script>
The state should be passed to the SsrTipserElementsProvider
on the browser side:
<TipserElementsProvider posId={POS_ID}>
<SsrTipserElementsProvider initialState={window.TIPSER_STATE}>
<App/>
</SsrTipserElementsProvider>
</TipserElementsProvider>,
Native apps
Tipser Elements is a web-based library and currently we don't provide a native version for Android or iOS (let us know if you'd like us to build it for you!)
However it is possible to embed Elements in a native app if you are using WebViews. We recommend to follow one of the patterns described below.
Pattern 1: Full web integration
In case your articles are managed by a Web CMS and are displayed in WebView you can simply install and use Tipser Elements in your web articles. Just follow the instructions from Tipser Elements section, depending on your technology of choice.
The only customisation that we recommend is using customUrls.productUrl
configuration, as described below.
Replacing dialogs with redirects
By default, when a product tile is clicked, it opens a full screen product dialog. It may not be the desired behaviour in your mobile app. Set the configuration option: customUrls.productUrl
to a URL containing your product page to enable redirecting the user to the product page. That way pressing the "back" button will bring the user back to your article.
Pattern 2: API integration
If you want to deliver native experience to your users, you can build your custom native e-commerce components (product tiles, shopping cart icon, etc) and use Tipser Rest API to populate them. When following this pattern, only the checkout part must be displayed in a WebView.
Below is a basic example of a native view with a single product that opens Tipser checkout view when clicked.
Step 1: Rendering a product on your page
- Use the Tipser product API to get the product that you want to sell, e.g:
https://api.dev.tipser.com/v3/products/5d932be284da04000116ae3c?pos=<YOUR_POS_ID>
(please, replace the example product id with the desired product and the pos parameter with your own POS id) - Render your custom product component based on the response data
Here we describe displaying a single product. If you'd be interested to render multiple products, it's best to use the collections API.
Step 2: Opening the checkout view
- Build and host a Tipser Elements web application using the
<CheckoutPage />
component or<ModularCheckout />
component - Create a WebView screen in your app project
- When your custom "buy" button is clicked, open the WebView with the URL pointing to your hosted checkout page
If your use case is not covered in this section, please discuss it with your Tipser integration support person.
Updated 3 months ago