Welcome to Developers Documentation

This page is highly technical and is intended to document the features, flows and libraries that you can use in order to consume Etvas API, to display Etvas components, to allow your users to use Etvas Products and to make your products available for the customers.

How to use

This documentation is intended to be used as a step-by-step tutorial, selecting for reading one section after the other. You must also consider keeping it in your bookmarks as a quick reference in your development process.

Errata

We strive to keep this documentation as complete as possible and in sync with our code. However, there are cases and periods of time in which these aspects are not accurate. If you spot inadvertences, errors or incomplete descriptions in this documentation, please tell us using the contact form. We will fix it as soon as possible.

Calling Etvas API

Etvas API is available at https://api.helloetvas.com and exposes both ReST and GraphQL endpoints. You should never directly access the endpoints from your FrontEnd application.

Calling the Etvas API endpoints involves supplying an API Key and signing the requests with a Secret key.

How authentication works

Here at Etvas we approach the communication security with high diligence. We are using the AWS recommended practices on all our security related flows and we use industry standards encryption algorithms and methods to achieve the best solutions.

Due to the complexity of Etvas platform, we have many authentication mechanisms, each with it's own authorization and scopes.

This document describes two types of authentication, both taking place in the server-to-server dialogue. The first one comprises in an API key and a secret key. The API key is somewhat public, meaning it travels with each request in a special header (x-api-key) and serves, in a way, to identify the caller, like a username. The API key is unique to you and it must be accompanied by the organization ID.

A first step for Etvas API is to check if the API key is correctly paired with the organization Id. Other complex checks are performed by Etvas API and AWS infrastructure to determine if the call is not an attack.

Once the API key is verified, Etvas platform checks if the signature you computed for the request is valid. The signature is computed with a HMAC/RSA256 algorithm using the API Secret. The API Secret NEVER travels through Internet. If this value is leaked, you must re-generate a new one at once, using your Partners Portal account, and update your environment file with the new value.. Once you've done that, the old API secret will no longer be valid. If someone with malicious intent gets a hold of your API Secret, they can make calls in your name. Etvas API will try to identify these calls, but chances are they will succeed.

Getting your API and Secret Key

TBD

Your keys are available by logging in into the Partners Portal with your account and selecting the Developer section.

The use of the API key is quite simple: it is to be sent with each request as a header (x-api-key):

HTTP/1.1 GET https://api.helloetvas.com/ping
Accept: application/json
x-api-key: demo-1234

Signing requests

In order for the Etvas API to allow a request, it must verify two things:

  • The identity of the party sending the request, in order to decide if the operation requested is allowed for that known party
  • The integrity of the request, because anything sent over a public network (such as Internet) can be modified in transit.

The request attributes needed for correctly identify a request are:

  • the HTTP method (GET, POST, PUT, PATCH,...)
  • the query parameters
  • a sub-list of headers
  • the body (the payload)

Step 1 - prepare a canonical form for the payload and compute SHA-256 hash on it

Preparing a canonical form of the payload involves two concerns: calculating a SHA256 hash on the stringified version and sending the exact same stringified version with the request.

For the canonical version of the payload we use the JSON minified representation, meaning the unformatted (no spaces, no new lines) JSON string. With that string, we simply calculate the SHA256 hash and get the hexadecimal digest of it. For Node JS, the code should be similar (if not identical) with the following one:

const payload = {
  id: "1234",
  name: "Jon Appleseed"
}

function createCanonicalPayload(obj) {
  return JSON.stringify(obj);
}

function createHashPayload(canonical) {
  return crypto
    .createHash('sha256')
    .update(canonical)
    .digest('hex')
}

const canonicalPayload = createCanonicalPayload(payload)
const hashPayload = createHashPayload(canonicalPayload)

Please note, for GET requests or even for other verbs with no payload, you should always include the SHA256 hash of an empty string. The hex representation of SHA256 hash for an empty string is always 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'.

Step 2 - create a canonical form for the request attributes and create HMAC/SHA256 signature

Next we will pack the relevant request data into a canonical form and use it. The canonical form is computed as lines separated by \n, comprising of:

  • Line 1: The ReST verb (GET, POST, PUT, PATCH, DELETE); example: GET
  • Line 2: The absolute path (without the base URL); example: /users/profile
  • Line 3: Any query string; example: foo=bar&baz=foo
  • Line 4: Content header; example: content-type:application/json
  • Line 5: Api Key header; example: x-api-key:1234-demo
  • Line 6: Current timestamp; example: x-timestamp:123155100
  • Line 7: the body hash; example: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

At this step, you should eliminate the empty lines (often, the third line will be empty). Here is an implementation example that you can use out-of-the-box in Node JS:

function createCanonicalRequest(
  method = 'GET',
  path = '/',
  qs = '',
  headers,
  bodyHash)
  {
    const contentType = headers && (
      headers['Content-Type'] ||
      headers['content-type'] ||
      headers('Content-type')
    )
    const etvasContext = headers && headers['x-etvas-context']
    const timestamp = headers && headers['x-timestamp']
    const apiKey = headers && headers['x-api-key']
    const lines = [
      method.toUpperCase(),
      path,
      query && query,
      contentType && `content-type:${contentType}`,
      `x-api-key:${apiKey}`,
      etvasContext && `x-etvas-context:${etvasContext}`,
      `x-timestamp:${timestamp}`,
      bodyHash
    ]

    return lines
      .filter(line !!line)
      .join('\n')
  }

Now that we have a pretty complete canonical representation of the request,
we will sign it with our API Secret:

function sign(canonicalRequest, apiSecretKey) {
  return crypto
    .createHmac('sha256', apiSecretKey)
    .update(canonicalRequest)
    .digest('hex')
}

Now you can call the Etvas API endpoints, including the additional signature header:

Step 3 - send the request with additional signature header

const headers = {
  'content-type': 'application/json',
  'x-api-key': '1234-demo',
  'x-timestamp': Date.now()
}

const canonicalRequest = createCanonicalRequest(
  'GET',
  '/users/user_id',
  '',
  headers,
  canonicalPayload
)

headers['x-signature'] = sign(canonicalRequest)

const response = await axios({
  method: 'get',
  url: '/users/user_id',
  baseURL: 'https://api.helloetvas.com',
  data: canonicalPayload,
  headers: headers
})

Note: A 403 response would mean the signature is not correct.

Customer management

Your customer needs to be registered in Etvas platform in order to use Etvas Value Added Services. Once logged in (or when the customer wants access to Etvas sections), the customer data needs to be transferred to Etvas API.

You can store the Etvas information alongside your customer data or verify each time if your customer is also an Etvas Customer.

Creating an Etvas Customer

In order to create an Etvas Customer you need to POST the profile information to https://api.helloetvas.com/users. Here is the call:

HTTP/1.1 POST https://api.helloetvas.com/users
Content-Type: application/json
Accept: application/json
x-api-key: your_api_key
x-timestamp: 1623609821835
x-signature: computed_signature_hex
--
{
  "firstName": "Jon",
  "lastName": "Appleseed",
  "phoneNumber": "+4912312312345",
  "isPhoneVerified": true
  "locale": "de",
  "email": "email@example.com",
  "tosAgreedAt": 1623609831835,
  "tosAgreedIp": "8.8.4.4"
}

As you can see, the first and last name are two separate fields. The phoneNumber must be in international format, with the + prefix and the country code, no spaces, dashes or any other characters. Ideally the number is a mobile phone number. The isPhoneVerified attribute is a bool, indicating if you checked the ownership of the phone number or not. Verifying ownership usually involves sending a SMS with a PIN in the registration process. As the registration is on your side in this scenario, Etvas will not check this information. The locale attribute must be en or de. This value will be taken into account when sending various informative emails (such as purchase details, invoice, alerts, cancellation warnings and so on) and display various HTML rendered fragments.

The last two attributes refers to the Terms of Service, as the customers using Etvas platform need to agree with both the product or service and etvas Terms of Service. The tosAgreedAt contains the Javascript timestamp (number of milliseconds from Jan 1, 1970 00:00:00), and the tosAgreedIp is the IP address of the customers machine. Please note it must be a valid IP V4/V6 address.

A word about the IP address: we store the customer IP address for audit purposes only. We do not use it in any way to identify the customer or track its activity across requests.

A success response will have a very important piece of information:

HTTP/1.1
Content-Type: application/json
--
{
  ...
  id: 'fdeb90cb-39fc-483d-b2f9-1e55f70f56ba'
  ...
}

A 2XX response indicates success and a 4XX or 5XX indicates failure. Inspecting the response body gives you a hint about what went wrong.

This is an ID (UUID v4) generated by Etvas platform to uniquely identify the newly created user. You can chose to save this ID alongside your customer data, in order to quickly identify this user is connected with Etvas.

Getting an existing Etvas Customer

You might want to verify if the customer you have is connected to Etvas. You can do this by querying with a GET request the /users/[identifier] endpoint:

HTTP/1.1 GET https://api.helloetvas.com/users/fdeb90cb-39fc-483d-b2f9-1e55f70f56ba
Accept: application/json
x-api-key: your_api_key
x-timestamp: 1623609821835
x-signature: computed_signature_hex

The response resembles (if success), the one obtained when creating the customer.

Please note you can use not only the Etvas ID but also the customer's email:

HTTP/1.1 GET https://api.helloetvas.com/users/email%40example.com
Accept: application/json
x-api-key: your_api_key
x-timestamp: 1623609821835
x-signature: computed_signature_hex

In both cases, a 2XX response indicates success and a 4XX or 5XX indicates failure. Inspecting the response body gives you a hint about what went wrong.

Please note the email is in this case URL encoded, so the @ character becomes %40.

This way, you can check the customer is connected with Etvas so you don't have to store the Etvas ID in your database. However, storing it will avoid a network call AND querying by ID instead of email is usually faster because you don't need to encode the ID (UUID format is already URL Safe).

Deleting a customer

In order to be GDPR compliant, you need to be able to delete the customer data when requested. If this is the case, you need to also delete this information in Etvas platform, prior to deleting it from your database.

Warning: Deleting a customer from Etvas platform means the immediate termination of all relations between the customer and Etvas. We will not only delete the profile data and anonymize attached information, but also we'll immediately cancel all ongoing subscriptions for purchased products and services and deny access to using said products and services. This operation cannot be recovered.

To delete a customer from Etvas Platform you need to call the same endpoint but with a DELETE HTTP verb:

HTTP/1.1 DELETE https://api.helloetvas.com/users/fdeb90cb-39fc-483d-b2f9-1e55f70f56ba
Accept: application/json
x-api-key: your_api_key
x-timestamp: 1623609821835
x-signature: computed_signature_hex

Of course, you can use URL encoded email instead of ID:

HTTP/1.1 DELETE https://api.helloetvas.com/users/email%40example.com
Accept: application/json
x-api-key: your_api_key
x-timestamp: 1623609821835
x-signature: computed_signature_hex

In both cases, a 2XX response indicates success and a 4XX or 5XX indicates failure. Inspecting the response body gives you a hint about what went wrong.

Obtaining a SSO token for an existing customer

You can obtain a SSO token for any existing customer you created by using a POST request with the following signature:

HTTP/1.1 POST https://api.helloetvas.com/users/email%40example.com/sso
Accept: application/json
x-api-key: your_api_key
x-timestamp: 1623609821835
x-signature: computed_signature_hex
--

The successful response will resemble:

HTTP/1.1
Content-Type: application/json
--
{
  token: 'sso_token'
}

This token is to be injected in Etvas Automat, and so make calls within a SSO customer authenticated context.

Allow customers to use purchased products and services

Each purchased product has a separate application, fully interfaced with Etvas Platform, which will allow the customer to use the product. For this, you must obtain a use purchased product token for a customer.

Here's how:

HTTP/1.1 POST https://api.helloetvas.com/users/email%40example.com/products/[product_id]/use
Accept: application/json
x-api-key: your_api_key
x-timestamp: 1623609821835
x-signature: computed_signature_hex
--

This will trigger a JSON response in the following form:

HTTP/1.1
Content-Type: application/json
--
{
  token: 'use_token'
}

The token is intended to be transmitted and used with Etvas Automat.

Single Sign On - Server to Server

In order to achieve the best User Experience, Etvas implements a SSO mechanism to be used exclusively in a Server-to-Server dialogue.

Please note this mechanism is available ONLY for users created with the methods described in "Calling API" documentation. A user self-registered in Etvas Platform or a user registered by other partner in the same manner will not be available for SSO in your context.

Logging in a customer behind the scenes requires a dialogue between your BackEnd and Etvas Backend and between your BackEnd and your FrontEnd. The usual flow is described below:

  1. The customer logs in in your FrontEnd Application and requests access to Etvas.
  2. Your FrontEnd Application calls your BackEnd to get the Etvas login token
    2.1. Backend checks if the current customer has an account with Etvas
    2.2. If not, calls POST to Etvas Backend to register the user and receive the Etvas User ID
    2.3. POST to the /sso endpoint with the Etvas Customer ID (or email) to obtain a token
    2.4. Pass the token back to the FrontEnd application
  3. The FrontEnd application uses Etvas Automat to obtain a login for the current user using the token received.

Installing and initializing Etvas Automat

Etvas Automat is a Javascript library you can use in your FrontEnd application to manage various aspects of User Interface regarding Etvas Platform.

Installing Etvas automat without a package manager

Use a <script> tag to reference the package. Using this method will register an object called etvasAutomat in the global window object. You can use it like this:

<!doctype html>
<html>
  <head>
    ...
    <script src="https://unpkg.com/@etvas/etvas-automat@latest"></script>
    ...
  </head>
  <body>
    ...
    <script>
      // in most cases you can omit window reference,
      // but we always recommend using like:
      window.etvasAutomat.initialize({ ... })
    </script>
  </body>
</html>

If you need a specific version of Etvas Automat, you can use the version number (for example 1.3.0) instead of latest:

  <script src="https://unpkg.com/@etvas/etvas-automat@1.3.0"></script>

You can read more about resolving a version (major, minor and so on) by consulting the documentation at unpkg.com.

Installing Etvas automat with a package manager

In most cases, your FrontEnd application uses a package manager like npm or yarn to solve the dependencies. Etvas automat is ready to be used with both, wether you use Vanilla Javascript, you have a React, Vue, Angular or any other FrontEnd framework to develop your application.

$ npm install @etvas/etvas-automat --save`

or, if you prefer yarn:

$ yarn add @etvas/etvas-automat

You can use the package as you normally use any other package. If you are using the CommonJS syntax, you can require the package like this:

const automat = require("@etvas/etvas-automat");
automat.initialize({ ... });

But, as this is a Front-End SDK, you might want to use the import syntax:

import automat from "@etvas/etvas-automat";
automat.initialize({ ... });

Initializing the library

The library needs some configuration in order to work and communicate properly with our backend services. We do that by calling a function named initialize. You will want to call this function as early as possible in your code, making sure it is the first one called:

automat.initialize({
  etvasURL: "https://unique-organization-slug.helloetvas.com",
  organizationId: "12345678-1234-1234-4123-123456789012"
})

Both EtvasURL and organizationId values are available in your account on Partners Portal.

Using Etvas Automat for SSO

With the token you obtained from your BackEnd, you can sign in the customer with Etvas. Any further call you run on Etvas Automat will use the login information to automatically authenticate the customer.

The function signature is:

automat.connect(ssoToken, callback = null)

where ssoToken is the token you obtained from your BackEnd services.

You can call this function at any time. The function is an async function and you can wait for it to finish (maybe displaying a loading indicator in your front-end) in two ways: providing a callback or using async/await:

// using callback:
function onConnect(err, success) {
  if (err) {
    alert('Could not successfully connect')
  } else {
    alert('Connection succeeded!')
  }
}
etvasAutomat.connect(ssoToken, onConnect)


// using async/await:
const etvasConnect = async (ssoToken) => {
  try {
    await etvasAutomat.connect(ssoToken)
    alert('Connection succeeded!')
  } catch (err) {
    console.error('Error caught while connecting to Etvas', err)
    alert('Could not successfully connect!')
  }
}

etvasConnect(ssoToken)

Logging out and exiting the SSO context is an easy task:

etvasAutomat.logout()

This will erase the SSO information and clear the Etvas Automat SSO cache.

Using Etvas Automat

Note: All the code examples assume you are using Etvas Automat as a package with a package manager and you use the ES6 syntax. Also, we will not include the initial code (like import and the call to initialize). If you need code examples for Vanilla Javascript, please contact us.

Etvas Automat offers various methods to interact with product listings, purchases and account settings. It is built to offer building blocks for you to use and inject in containers (divs) in your application.

With Etvas Automat, you can:

  • query for products listing

  • query for a product details

  • display the Purchase modal

  • display Use Product (allow customer to use a purchased product)

  • display a product card

  • display a product details page

  • display the list of products and services you published

  • display Etvas Platform Terms Of Service

  • display Product specific Terms Of Service

  • display Etvas account settings page

Please note, some of the functionalities are available only after a successful connect operation and others will have different results if the connect call took place or not. For each of these operations, the documentation will indicate this aspect.

All the query calls respect the syntax where the the first argument is a string describing the endpoint (or query) you want to obtain a response from; the second argument can be a params object, if the query requires it; the next argument is an options object, and the last one is a callback for use without async/await syntax. Only the first argument is always required. Depending on the query, the params argument might be required as well. As for the options, it will always have a default value (so it can be omitted) and the callback always optional.

Using SSO with all Etvas Automat function calls

A special attribute in the options object is worth a note, the sso: if the sso attribute is present, it can be:

  • a true boolean value, meaning use the login if already injected by calling connect in a prior code fragment;
  • a false boolean value, meaning the library should not use login information even if already present;
  • a string value containing a token, meaning the call to connect will be automatically performed.

Here are the three examples, explained:

Example 1 - instruct not to use SSO

await etvasAutomat.connect(ssoToken)
const response = await etvasAutomat.query('products', {
  sso: false
})

which is identical to:

await etvasAutomat.connect(ssoToken)

// ...

await etvasAutomat.logout()
const response = await etvasAutomat.query('products')

Even if the SSO login for the customer was successfully injected into Etvas Automat, the call to the products query will not use SSO and the call is unauthenticated. The call will invoke the logout method on Etvas Automat.

Warning: Calling any method with sso: false in options will trigger a system wide logout, meaning any calls after this one will not be in SSO context.

Example 2 - use SSO if available - the default behavior

If a prior call to connect was successfully performed, the following calls will use SSO when performing the query.

const response = await etvasAutomat.query('products')
// or use the following one, with the same results:
const response = await etvasAutomat.query('products', { sso: true })

Example 3 - use SSO inline

const ssoToken = await obtainSSOTokenFromBackend()
const response = await etvasAutomat.query('products', { sso: ssoToken })

will behave exactly as:

const ssoToken = await obtainSSOTokenFromBackend()
await etvasAutomat.connect(ssoToken)
const response = await etvasAutomat.query('products')

As expected, the call to a query method with a string sso in options will automatically trigger the connect method prior to performing the query. However, it is worth noting that Etvas automat will cache the SSO information so other calls after the first one will re-use the sso token if options.sso is true, undefined or a string with the same value.

So, the following example will both return authenticated results, even if the connect function was never called directly:

const ssoToken = await obtainSSOToken()
// the next function will call connect internally and store the login data
// and the products will have information in authenticated context
const products = await etvasAutomat.query('products', { sso: ssoToken })
// the next function call will be called in authenticated context, as well
const productDetails = await etvasAutomat.query(
  'productDetails',
  { id: products[0].id }
)

If this is not the desired behavior, pass sso: false in the options of the second query call:

const ssoToken = await obtainSSOToken()
// the next function will call connect internally and store the login data
// and the products will have information in authenticated context
const products = await etvasAutomat.query('products', { sso: ssoToken })
// the next function call will not be called in authenticated context
const productDetails = await etvasAutomat.query(
  'productDetails',
  { id: products[0].id },
  { sso: false }
)
// A third call will not have the SSO context setup:
const otherProductDetails = await etvasAutomat.query(
  'productDetails',
  { id: products[1].id }
)

Using queries to get information

You can use queries directly from Etvas Automat to get product information, such as the list of available (published) products, or product details for a specific one.

Querying products listing

The query name is products and the general signature is:

const etvasProducts = await etvasAutomat.query('products', options)

It will return an array of products, in authenticated context or not. The main difference lies in the product purchase status, which is known when authenticated.

Querying for product details

The query name is productDetails and the general signature is:

const params = { id: 'the-product-id' }
const etvasProductDetails = await etvasAutomat.query(
  'productDetails',
  params,
  options
)

Using iframes to display information

All the methods described below use iframes to display information embedded in your application. Each iframe has a mechanism to automatically resize itself vertically (using window.postMessage) based on the content, so you don't have to worry about the double-scroll. For the horizontal part, all the markup displayed in the iframe is built mobile-first, so it should automatically render itself according with the maximum width of the container you specify in the function calls. However, your application must not impose a height on the container, so the height will automatically accommodate the iframe dynamic height.

All the iframes displayed will have a default inline style like:

<iframe style="{ width:100%; border:none; display:block; }" ...></iframe>

A word on branding: All the iframes displayed by Etvas Automat will be rendered with respect to the branding values you specify in your Partners Portal account. This happens automatically.

Displaying the purchase modal

Please note, even we are using the modal term, you must handle the container yourself. The modal term only hints about how it should be displayed and not the actual mode. The function will inject the required HTML markup in a container of your choice, whether it is in a modal dialog or in a new page, for example. Please note the HTML markup injected is a iframe element.

The call to this function must be in SSO authenticated context and the product or service specified must not be already purchased by the current customer.

The general syntax is:

etvasAutomat.showPurchase(container, params, options)

Where:

  • container is required and it is either a HTML node element (obtained by calling document.getElementById('etvas-container) or similar) or directly specifying the ID of the HTML element as a string: etvas-container;
  • params is required and it is an object containing as a minimum the id of the product to be purchased (explained below in detail);
  • options is optional and follows the general syntax (with sso).

A complete example for the params object is explained below:

const onSuccess = (payload) => {
  console.info('Product purchased:', payload.id)
}

const onFailure = (error) => {
  console.error('Product was not purchased because', error.message)
}

const params = {
  productId: 'the_product_id',
  onSuccess: onSuccess,
  onFailure: onFailure
}

Allow customers to use a purchased product

When the customer purchases a product, the general behavior is to be able to use it right away. In order to do this, you must obtain a use product token. This token can be obtained for any purchased product, meaning you can generate such token in your application BackEnd.

// The getSSOLogin and getUseToken are two functions
// calling your backend implementation.

const handleAction = async ({productId, action }) => {
  closeModal()
  if (action === 'openProductUse') {
    etvasAutomat.showProductUse('full-page-container')
  } else {
    alert('Purchase was canceled by user')
  }
}

const params = {
  productId: 'the_product_id',
  onAction: handleAction
}

const ssoToken = await getSSOLogin()
await etvasAutomat.connect(ssoToken)
etvasAutomat.showPurchase(container, params)

Displaying a product card

The call for this function will inject an iframe in your web application. The product card contains the product title, a short description, an optional rating (1 to 5 stars) and a link. The title, description and link text are language-aware. Remember locale attribute when you initialized the Etvas Automat library? That is the value we will use to render these texts.

A product card will not take much space in the page. By default, the displayed iframe has the following inline style:

<iframe
  style="border:none; width:480px; height:240px; display:block;"
  src="...">
</iframe>

The general syntax is:

etvasAutomat.showProductCard(container, params, options)

where:

  • container is a HTML node element or a string referring to an ID of a HTML element;
  • params is an object describing how the product card is to be displayed
  • options is an object following the general format (sso option)

The params object has the following structure:

const params = {
  productId: 'uuid',    // the product ID of the rendered product
  append: false,        // false to clear the container before inserting iframe
  hideRating: false,    // true to hide the product rating
  showSeeMore: 'link',  // 'link', 'button' or false to hide
  seeMoreText: 'See details', // the text to be displayed in link,
  onAction: handleAction // a callback called when the customer clicks the link
}

The values (except the productId attribute) represents the defaults (if not specified). Using hideRating, showSeeMode and seeMoreText attributes allows you to configure the appearance of the product card.

Note: If you specify the seeMoreText you will lose the Internationalization on this label, so make sure you insert a string in the same locale you initialized the Etvas Automat.

You can control how the See more link is displayed. If you specify link (default) it will render a... well... a link. If you specify button it will render a button or, if you pass a boolean false it will hide the CTA.

Pro Tip: you can hide the Call to Action all together and make the entire card clickable by attaching a click event on the container you specify. In this case, make sure you implement your own click handler and do not expect the onAction handler to be called.

Although the seeMore is rendered as a link in the product card, it will not trigger an action when clicked by the customer. It's up to you to define this action in onAction handler.

If you are in SSO context, the product card might render a Use text instead of a See More text, if the product is already bought. In this case, the same onAction handler is called.

The click handler receives the product object. If SSO login is active, you will have the purchase status:

const handleAction = ({productId, action, ...props}) => {
  console.info(`Product `${name}` - ${productId} card clicked`, action, props)
  if (action === 'showProductUse') {
    console.info('The product is already bought by the customer')
  } else if (action === 'showProductDetails') {
    console.info('The customer wants to know more details about the product')
  }
}

Displaying a product details page

Displaying a product details page is similar with displaying a product card. Of course, the name of the function is different:

etvasAutomat.showProductDetails(container, params, options)

where:

  • container is a HTML node element or a string referring to an ID of a HTML element;
  • params is an object describing how the product details is to be displayed
  • options is an object following the general format (sso option)

The params object has the following structure:

const params = {
  productId: 'uuid',    // the product ID of the rendered product
  append: false,        // false to clear the container before inserting iframe
  hideRating: false,    // true to hide the product rating
  onAction: handleAction // a callback called when the customer clicks the link
}

With this iframe, the Call To Action button is always there, and it differs depending on wether the call is made in SSO context and if the product is already bought by the current customer, like this: if the call is outside SSO (unauthenticated), the button will always show a Purchase action, together with the price. If the call is within SSO context AND the product is purchased, the button will show Use product label.

In either case, the same handleAction handler will be called, but the behavior should be implemented differently (login / register customer or present the product use iframe).

The payload for the callback will include the productId and the type of button displayed (and pressed).

Displaying the list of products

In Etvas, displaying all the products in a page is called Discover, thus allowing the customer to discover the products and services available for purchase. If the customer is logged in (in SSO context), the product listing will contain indication on which product is already purchased (an active subscription) or available to be purchased.

As always, you must specify a HTML node to act as container, pass some parameters and, optionally, specify the SSO options:

etvasAutomat.showDiscover(container, params, options)

where:

  • container is a HTML node element or an ID of a HTML node element;
  • params an object that controls the behavior of the product listing;
  • options an object containing the SSO options for this call;

The params object has the following structure:

const params = {
  append: false, // set this to true to append the iframe to the container
  onAction: actionHandler
}

function actionHandler ({ productId, action }) {
  switch(action) {
    case 'openProductDetails':
      alert('opening product details for ' + productId)
      // call the showProductDetails function:
      // etvasAutomat.showProductDetails(container, { productId, onAction: actionHandler })
      break
    case 'openProductPurchase':
      alert('opening purchase flow for product ' + productId)
      // call showProductPurchase function:
      // etvasAutomat.showProductPurchase(modalContainer, { productId, onAction: actionHandler })
    case 'openProductUse':
      alert('should open product use for ' + productId)
      // retrieve a Use URL from BackEnd and call:
      // etvasAutomat.showProductUse(container, { productId })
      break
    default:
      throw new Error('Unknown action ' + action)
  }
}

Displaying the list of purchased products

This function will render a list with all purchased products for a logged customer. Of course, it makes sense to call it only in SSO authenticated context. The function signature is:

etvasAutomat.showMyProducts(container, params, options)

As always, the container must be a HTML node element or a string containing the unique ID of a HTML node element, and the options refers to SSO options.

The params object has the following structure:

const params = {
  append: false,  // true to append the iframe in the container
  onAction: handleAction
}

function handleAction({ productId, action }) {
  switch(action) {
    case 'openProductDetails':
      alert('opening product details for ' + productId)
      // call the showProductDetails function:
      // etvasAutomat.showProductDetails(container, { id: productId })
      break
    case 'openProductPurchase':
      alert('opening purchase flow for product ' + productId)
      // call showProductPurchase function:
      // etvasAutomat.showProductPurchase(modalContainer, { id: productId })
    case 'openProductUse':
      alert('should open product use for ' + productId)
      // retrieve a use URL from BackEnd and call:
      // etvasAutomat.showProductUse(container, { url })
      break
    case 'openDiscover':
      alert('The current user has no purchased products')
      // the user clicked on the Show Discover button
      // on the Empty Product Listing view
      // should naturally show the discover page and use the same handler
      // etvasAutomat.showDiscover(container, { onAction: actionHandler })
    default:
      throw new Error('Unknown action ' + action)
  }
}

As you can see, you could use the same handler for all the calls.