Voyado

How to get started and work with Voyado

NB: This requires configuration in internal systems in order to work.

If not configured properly, you'll get presented with the following error:

Copy
Copied
{
  "message": "Internal system responded with status code NotImplemented",
  "extensions": {
    "code": "ExternalCustomerLookupFailed",
    "codes": ["ExternalCustomerLookupFailed"]
  }
}

external customer lookup

For the lookup you'll be using the externalCustomerLookup endpoint with a key argument. The key is configured internally and can be one of the following: email, phone or pid. The action you should be doing differs depending on the response from the endpoint, meaning you are able to end up in five different states, presented below.

Call externalCustomerLookup
NON_EXISTING_CUSTOMER
PREEXISTING_CUSTOMER
ACTIVATION_REQUIRED
COUNTRY_NOT_VALID
ADDITIONAL_USER_DATA_REQUIRED
lookup-queryvoyado-lookup-outputlookup-output-additional-data-requiredlookup-output-activation-requiredlookup-output-existing-customer
Copy
Copied
query ExternalLookup($key: String) {
  externalCustomerLookup(key: $key) {
    status
    customer {
      firstName {
        masked
        encrypted
      }
      externalId
    }
  }
}
Copy
Copied
{
  "data": {
    "externalCustomerLookup": {
      "status": "NON_EXISTING_CUSTOMER",
      "customer": null
    }
  }
}
Copy
Copied
{
  "data": {
    "externalCustomerLookup": {
      "status": "ADDITIONAL_USER_DATA_REQUIRED",
      "customer": {
        "firstName": {
          "masked": "Er**",
          "encrypted": "eTZ7FGaVn/RAThBesp3unQ=="
        }
        "email": {
          "masked": "h*j@o**ry.cool",
          "encrypted": "a3k/eW8DeaassJrelr2xuw=="
        },
        "externalId": "af083b2e-1a88-42ae-afbc-ac63008e277d"
      }
    }
  }
}
Copy
Copied
{
  "data": {
    "externalCustomerLookup": {
      "status": "ACTIVATION_REQUIRED",
      "customer": {
        "firstName": {
          "masked": "Aktivera",
          "encrypted": "Q8XIf+4IC6TMgLPYtFxi3Q=="
        },
        "email": {
          "masked": "h*j@o**ry.cool",
          "encrypted": "a3k/eW8DeaassJrelr2xuw=="
        },
        "externalId": "af083b2e-1a88-42ae-afbc-ac63008e277d"
      }
    }
  }
}
Copy
Copied
{
  "data": {
    "externalCustomerLookup": {
      "status": "PREEXISTING_CUSTOMER",
      "customer": null
      }
    }
  }
}

Keep in mind here that you're supposed to take action based on the response inside status field. For example, if the status is NON_EXISTING_CUSTOMER then you likely want to present a signup form and so on.

As you may have noticed, we only return the customer data when status is either ACTIVATION_REQUIRED or ADDITIONAL_USER_DATA_REQUIRED. ADDITIONAL_USER_DATA_REQUIRED means there are fields present and required in Norce admin, but the information is missing in Voyado. The customer object returns all needed fields for an actual signup. Each data point inside the customer object is masked or encrypted. The masked data can be presented as information or as a prefilled form. The encrypted values should be sent in as SignupInput in order for our backend to decrypt them.

person lookup

In some cases the client is using a third party to fetch information based on PID. This is done from within Voyado but should be queried from our StoreAPI. In these cases you'd want to use the personLookup endpoint. This is useful when the end user is not registered and you want a prefilled form based on the response. Same logic applies to this action, prefill form with masked data and send the encrypted ones as SignupInput.

personlookup-querypersonlookup-output
Copy
Copied
query PersonLookup($key: String) {
  personLookup(key: $key) {
    firstName {
      masked
      encrypted
    }
  }
}
Copy
Copied
{
  "data": {
    "personLookup": {
      "firstName": {
        "masked": "Einár",
        "encrypted": "eTZ7FdwVn/RAThadBesunQ=="
      }
    }
  }
}

activate customer by id

In order for the Norce - Voyado to work the customer must exist in both Voyado and Norce. The status ACTIVATION_REQUIRED is returned when the customer exists in Voyado, but not in Norce. This is where you'd want to use the activateExternalCustomerById endpoint. The only required argument for this endpoint is the returned value in externalId you got from the lookup query.

activation-by-id-mutationactivation-by-id-mutation-success
Copy
Copied
mutation ActivateByExternalId($input: ActivateExternalCustomerByIdInput) {
  activateExternalCustomerById(
    input: $input
  ) {
    success
    token {
      value
    }
  }
}
Copy
Copied
{
  "data": {
    "activateExternalCustomerById": {
      "success": true,
      "token": {
        "value": "<your token>"
      }
    }
  }
}

If the activation succeded, we'll automatically send an email to the customer, where they are able to set a password for the account. This email is only editable by our product support. You can however use the token to do a soft login. Soft logged in means the customer have access to personal information and discounts, they are able to make a purchase but they are not able to change any information regarding the account.

active customer by token

The second option for account activation is to click a link from within a promotion email sent by Voyado. This time we'll be using the activateExternalCustomerByToken endpoint, the argument is the token appended by Voyado in the promotion email link.

activation-by-token-mutationactivation-by-token-mutation-successactivation-by-token-mutation-addition-data-required
Copy
Copied
mutation ActivateByToken($input: ActivateExternalCustomerByTokenInput) {
  activateExternalCustomerByToken(
    input: $input
  ) {
    success
    customer {
      firstName {
        masked
        encrypted
      }
      email {
        masked
        encrypted
      }
      externalId
    }
  }
}
Copy
Copied
{
  "data": {
    "activateExternalCustomerByToken": {
      "success": true,
      "customer": null
    }
  }
}
Copy
Copied
{
  "errors": [
    {
      "message": "AdditionalUserDataRequired",
      "extensions": {
        "code": "InvalidCustomerActivateInput",
        "codes": [
          "InvalidCustomerActivateInput"
        ]
      }
    }
  ],
  "data": {
    "activateExternalCustomerByToken": {
      "success": false,
      "customer": {
        "firstName": {
          "masked": "Er**",
          "encrypted": "eTZ7FGaVn/RAThBesp3unQ=="
        },
        "email": {
          "masked": "a*d@je***op.se",
          "encrypted": "Iyafl0B5de6zG+++YS9caw=="
        },
        "externalId": "220999da-3f78-45a4-91b3-ac6200e7a416"
      }
    }
  }
}

In this scenario too, the customer may end up in a AdditionalUserDataRequired state where you have an option to either fail the activation and persist the url the customer tried to visit, or to redirect to a signup form. If succeded, keep in mind that this always soft logins the customer.

loyalties

Loyalties can be unique for each customer and can only be queried for when a valid Authorization header is present. All loyalties are added in Voyado.

loyalties-queryloyalties-query-output
Copy
Copied
query Loyalties($includeRedeemed: Boolean!) {
  customerLoyalty {
    bonusChecks {
      name
      redeemed
      value
    }
    pointCards {
      name
      numberOfSlots
      numberOfSlotsRemaining
    }
    discounts(includeRedeemed: $includeRedeemed) {
      name
      description
      isActivatedByDiscountCode
      discountCode
    }
    bonusPoints {
      points
    }
  }
}
Copy
Copied
{
  "data": {
    "customerLoyalty": {
      "bonusChecks": [
        {
          "name": "Bonusutbetalning 2021-12-02 10:00",
          "redeemed": false,
          "value": 600
        }
      ],
      "pointCards": [],
      "discounts": [
        {
          "name": "Alla glada",
          "description": "",
          "isActivatedByDiscountCode": false
          "discountCode": null
        }
      ],
      "bonusPoints": {
        "points": 0
      }
    }
  }
}

complete lookup flow example

NB: This is an exmpale on how you could present your UI when utilizing all or some of the lookup and activation endpoints.

Calls externalCustomerLookup
NON_EXISTING_CUSTOMER
PREEXISTING_CUSTOMER
ACTIVATION_REQUIRED
COUNTRY_NOT_VALID
ADDITIONAL_USER_DATA_REQUIRED
If configured,
manually/automatically calls personLookup
Yes
No
Manually/automatically calls
activateExternalCustomerById
No
Yes
Manually/automatically login
Customer fills LookupField
Lookup success
Returns no customer data
Can login
Returns masked and
encrypted customer data
Returns countryCode
Returns masked customer data
Customer manually
fills required fields
Customer data found
Prefills signup form
with personLookup response
Success
Present error message / try again
Customer activated
Returns temporary auth token
Soft logged in
Present error message
Populates signup form
with masked data
Customer manually fills in
missing required data
Can create customer

complete softlogin flow example

NB: This is an exmpale on how you could present your UI when utilizing all or some of the activation endpoints.

Automatically
calls loginExternalCustomer
No
Yes
Yes
No
Yes
No
No
Yes
NON_EXISTING_CUSTOMER
ADDITIONAL_USER_DATA_REQUIRED
ACTIVATION_REQUIRED
PREEXISTING_CUSTOMER
Yes
No
Customer clicks campaign link with hash
Was customer logged in?
Is activation on softlogin configured
Continue to campaign destination
with personal discounts
Calls activateExternalCustomerByToken
Is redirect on activation
failure configured
Signup page
Continue to campaign destination
without personal discounts
Customer found?
Checks customer status
Is activation on
softlogin configured
Copyright © Norce 2023. All right reserved.