Skip to content

Sending visitor variables (HTTP API)

Overview

You can attach key value pairs to visitors with giosg REST API's. This data is then available to operators in giosg console and on new giosg and also in reporting. For this method there is no need for a separate signing of the data because the data is sent from your server and the API's are authenticated with an api token created in your account.

Prerequisites

You will need API token, see Authentication with an API token.

Once you have obtained your API token, define the Authorization HTTP header for all your API requests:

Authorization: Token <api_key>

You should replace the <api_key> with your API token

Remember that the API token is connected to the user that created the token which means that if the user is deleted also the token is invalidated. You can create an extra user and create the token with this user, remember to name the user so that it doesn’t get deleted by mistake e.g “Reporting api-user do not delete”

Setup in giosg account to only accept signed/authorized data

To enable the feature to only accept signed/authorized variables in your giosg room navigate to: Settings->Rooms->{room_name}-> Security and Encryption-> tick the checkbox below the text: "Always require signatures for visitor data and chat URLs" Screenshot

Create a chat visitor variable

For the below you will need the visitor id of the visitor on the page, this value can be obtained from the front-end and you need to pass it to your backend for setting the variables.

The visitor ID needed in the requests can be found when the giosg script has loaded from the window scope variable, see example below. You may also get the visitor ID from webhooks sent by Giosg platform or from fetching chat memberships though HTTP API.

1
2
3
4
5
_giosg(() => {
    window.GiosgClient.visitorGidDeferred.then(() => {
        console.log("Visitor CID:", giosg.unpackedVisitorCid);
    });
});

Endpoint for setting the visitor variables

POST /api/v5/orgs/<organization_id>/rooms/<room_id>/visitors/<visitor_id>/variables.

This endpoint returns:

  • 201 if the request was successful
  • 400 if required attribute is missing from the request
  • 400 if the request payload is in wrong format
  • 401 if you are not authenticated
  • 403 if you do not have active subscription
  • 403 if you do not have access to the organization
  • 403 if you do not have settings permission
  • 404 if the room was not found
  • 404 if the visitor was not found
  • 404 if the key was not found

Example request:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import requests

GIOSG_SERVICE_BASE_URL = "https://service.giosg.com"
api_token = "<giosg api token>"

organization_id = "<uuid>"
room_id = "<room_uuid>"
visitor_id = "<visitor_id>"

def set_variables(visitor_data):
    url = "{}/api/v5/orgs/{}/rooms/{}/visitors/{}/variables".format(
        GIOSG_SERVICE_BASE_URL,
        organization_id,
        room_id,
        visitor_id
    )
    headers = {
        'Authorization': 'Token ' + api_token
    }
    response = requests.post(url, headers=headers, json=visitor_data)
    response.raise_for_status()
    return response.json()

# Call function to submit visitor variables
set_variables({
    "key": "username",
    "value": "Bill"
})
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const orgId = '<org_id>';
const apiToken = '<Api_token>';
const roomId = '<room_id>';
const visitorId = '<visitor_id>';

async function setVariables(url = "", data) {
    const response = await fetch(url, {
        method: "POST",
        body: JSON.stringify(data),
        headers: {
            "Content-Type": "application/json",
            Authorization: `Token ${apiToken}`,
        },
    });
    return await response.json();
}

const url = `https://service.giosg.com/api/v5/orgs/${orgId}/rooms/${roomId}/visitors/${visitorId}/variables`;
const visitorVariables = {
    key: "username",
    value: "Bill"
};
setVariables(url, visitorVariables).then((data) => {
    console.log(data);
});

Example response:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
{
    "visitor_id": "c8cf0752af4de2ac26dfd84a24c61d75",
    "room_id": "c4570f58-ca53-11e9-bb02-0242ac110015",
    "key": "username",
    "value": "Bill",
    "session_id": "8ef88010-6d29-11eb-88ef-0242ac110004",
    "created_at": "2021-02-12T12:03:21.254Z",
    "updated_at": "2021-02-12T12:03:21.254Z",
    "is_signed": true,
    "is_encrypted": false,
    "encrypted_value": null,
    "encrypted_symmetric_key": null
}

Remove submitted variables and end the chat-session on logout

Usually the visitor variables are set when a user logs in on your page, it is strongly recommended to also remove these variables when the user logs out or session expires and end the chat sessions so that no one else on the same device can access the other users chats.

For removing the variables and ending the chats from all of your rooms can be done both with REST API call and javascript API.

Removing visitor variables and ending chat with REST API

Overview of the workflow for ending the chats for a visitor, the visitor_id is the same that you used for submitting the variables: - List all rooms for the organization - Fetch chats for the visitor for each room - Iterate over the open chats and call the chat_end api

Ending the chats for the visitor

To list all the organization rooms (needed to fetch the open chats for a visitor) see listing rooms of organization.

GET https://service.giosg.com/api/v5/orgs/<organization_id>/rooms

When you have the list of the rooms you can loop through the list to get all the ongoing chats for a visitor, remember to add the parameter: is_ended=false: to only receive a list of currently active chats for the user.

GET /api/v5/orgs/<org_id>/rooms/<room_id>/visitors/<visitor_id>/chats?is_ended=false

You can then end each ongoing chat for the room by calling following endpoint for all of the ongoing chats of the visitor: see End organization's owned chat

PATCH /api/v5/orgs/<organization_id>/owned_chats/<chat_id>

You need to define the is_ended attribute with value true as a payload:

1
2
3
{
    "is_ended": true
}
Example request:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import requests

GIOSG_SERVICE_BASE_URL = "https://service.giosg.com"
api_token = "<api_token>"
organization_id = "<org_id>"
visitor_id = "<visitor_id>"

def end_chats():
    headers = {
        'Authorization': 'Token ' + api_token
    }
    # Fetch all the rooms for the organization and add to list if it's not deleted
    room_list_url = "{}/api/v5/orgs/{}/rooms?is_deleted=false".format(GIOSG_SERVICE_BASE_URL, organization_id)
    room_response = requests.get(room_list_url, headers=headers)
    room_response.raise_for_status()
    rooms = room_response.json()
    room_ids = []

    for room in rooms['results']:
        if not room['is_deleted']:
            room_ids.append(room['id'])

    #fetch all the active chats for the visitor and add to list
    for room_id in room_ids:
        room_chats_url = "{}/api/v5/orgs/{}/rooms/{}/visitors/{}/chats?is_ended=false".format(GIOSG_SERVICE_BASE_URL, organization_id, room_id, visitor_id)
        chat_response = requests.get(room_chats_url, headers=headers)
        chat_response.raise_for_status()
        # Assuming here that we only have one page of results.
        # See https://docs.giosg.com/api_reference/common_api_guidelines/#paginated-collections for handling pagination
        chat_list = chat_response.json()

        # End the chats for the visitor:
        if chat_list['results']:
            for chat in chat_list['results']:
                chat_url = "{}/api/v5/orgs/{}/owned_chats/{}".format(GIOSG_SERVICE_BASE_URL, organization_id, chat['id'])
                end_response = requests.patch(chat_url, headers=headers, json={ "is_ended": True })
                end_response.raise_for_status()
                chat_end_response = end_response.json()
                print(chat_end_response)

# Call to end chats of the visitor
end_chats()

Removing the submitted variables

DELETE /api/v5/orgs/<organization_id>/rooms/<room_id>/visitors/<visitor_id>/variables/<key>.

This endpoint returns:

  • 204 if the request was successful
  • 401 if you are not authenticated
  • 403 if you do not have active subscription
  • 403 if you do not have access to the organization
  • 403 if you do not have settings permission
  • 404 if the room was not found
  • 404 if the visitor was not found
  • 404 if the key was not found

Removing visitor variables and ending chat with javascript API

Overview of the workflow for ending the chats for a visitor, the visitor_id is the same that you used for submitting the variables: - List all rooms for the organization - Fetch chats for the visitor for each room - Iterate over the open chats and call the chat_end api

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
const serviceUrl = "https://service.giosg.com"
const orgId = '<org_id>';
const apiToken = '<api token>';
const visitorId = '<visitor id>';

async function getRooms() {
    const roomListUrl = `${serviceUrl}/api/v5/orgs/${orgId}/rooms?is_deleted=false`;
    const response = await fetch(roomListUrl, {
        method: "GET",
        headers: {
            "Content-Type": "application/json",
            Authorization: `Token ${apiToken}`,
        },
    });
    return (await response.json())["results"];
}

const endChats = async () => {
    // Fetch all the rooms for the organization
    const rooms = await getRooms();
    const roomIds = rooms.filter(r => !r.is_deleted).map(room => room.id);

    // Fetch all the active chats for the visitor and add to list
    roomIds.forEach(async roomId => {
        const roomChatsUrl = `${serviceUrl}/api/v5/orgs/${orgId}/rooms/${roomId}/visitors/${visitorId}/chats?is_ended=false`;
        const chatResponse = await fetch(roomChatsUrl, {
            method: "GET",
            headers: {
                "Content-Type": "application/json",
                Authorization: `Token ${apiToken}`,
            },
        });
        const chats = (await chatResponse.json())["results"];

        chats.forEach(async chat => {
            const chatUrl = `${serviceUrl}/api/v5/orgs/${orgId}/owned_chats/${chat.id}`;
            if (!chat.is_ended) {
                console.log("Ending chat:", chatUrl);
                const endRespoonse = await fetch(chatUrl, {
                    method: "PATCH",
                    body: JSON.stringify({"is_ended": false}),
                    headers: {
                        "Content-Type": "application/json",
                        Authorization: `Token ${apiToken}`,
                    },
                });
                const response = await endRespoonse.json();
                console.log(response);
            }
        });
    });
}
// Call to end chats
await endChats();

Removing the submitted variables

DELETE /api/v5/orgs/<organization_id>/rooms/<room_id>/visitors/<visitor_id>/variables/<key>.

This endpoint returns:

  • 204 if the request was successful
  • 401 if you are not authenticated
  • 403 if you do not have active subscription
  • 403 if you do not have access to the organization
  • 403 if you do not have settings permission
  • 404 if the room was not found
  • 404 if the visitor was not found
  • 404 if the key was not found

Conclusion

In this tutorial we went through the process of submitting extra info about the visitor to the chat and removing the submitted information after the chat.

Endpoints used in this tutorial

/api/v5/orgs/<organization_id>/rooms/<room_id>/visitors/<visitor_id>/variables

/api/v5/orgs/<organization_id>/rooms

/api/v5/orgs/<org_id>/rooms/<room_id>/visitors/<visitor_id>/chats

/api/v5/orgs/<organization_id>/owned_chats/<chat_id>