Embed Analytical Designer Using Iframes

To embed a Analytical Designer into your web application, copy the following iframe snippet into your web app and subtitute your own values for <host_url>, <workspace_id> and <visualization_id>:

<iframe
    title="My Embedded GoodData Analytical Designer"
    id="embedded-app-frame"
    src="<host_url>/analyze/embedded/#/<workspace_id>/<visualization_id>"
    height="500px" 
    width="100%" 
    frameborder="0"
></iframe>

You may be prompted to authenticate yourself. Once authenticated, you should be able to see your embded Analytical Designer:

Analytical designer embeded within an iframe

To hide or display different parts of the Analytical Designer, see Configuration Options.

To use alternative ways of authentication, see Authentication.

To monitor and control the behaviour of the Analytical Designer using JavaScript, see PostMessages.

Configuration Options

You can configure your embedded Analytical Designer by adding one or more of the following URL parameters:

URL ParameterDescription
?hideControl=[topBar]Hide the top bar
?includeObjectsWithTags=[tag1,tag2]Display only objects that contain a tag listed in this parameter
?excludeObjectsWithTags=[tag1,tag2]Hide objects that contain a tag listed in this parameter

For example to embed a Analytical Designer without the top bar, you would use the following URL:

<host_url>/analyze/embedded/#/<workspace_id>/<visualization_id>?hideControl=[topBar]

Authentication

If you are using an OpenID Connect (OIDC) identity provider for authentication, the authentication process should be automatic. However, if you want to use API tokens for authentication, you will need to handle this type of authentication manually.

Use API Token

To set up authentication using API token for an embedded Analytical Designer:

  1. Embed the Analytical Designer using the iframe.

  2. Add URL parameter ?apiTokenAuthentication=true.

  3. Implement a message listener in the embedding page to listen to events sent by the Analytical Designer. The listener must wait for a listeningForApiToken event.

    When the event is received, the Analytical Designer is ready to receive the API token.

  4. Send a postMessage command to the iframe with the API token value.

    The Analytical Designer will continue with initialization and use the token for authentication of all API calls from now on.

See the Example below for implementation details.

Example of Authentication Using Injected API Token

You may reuse the following code snippet, do not forget to replace <host_url>, <workspace_id>, <visualization_id>, and <api_token_value> with your own values:

<iframe
    title="Embed GD Application"
    id="embedded-app-frame"
    src="<host_url>/analyze/embedded/#/<workspace_id>/<visualization_id>?apiTokenAuthentication=true"
    width="1300"
    height="800"
></iframe>
<script>
    console.log("Setup parent frame message listener")

    window.addEventListener(
        "message",
        function (event) {
            console.log("Post message received", event);

            if (event.data.gdc?.event.name === "listeningForApiToken") {
                const postMessageStructure = {
                    gdc: {
                        product: "analyticalDesigner",
                        event: {
                            name: "setApiToken",
                            data: {
                                token: "<api_token_value>"
                            }
                        }
                    }
                };
                console.log("Sending token to embedded window");

                const origin = "*";
                const iframe = document.getElementById("embedded-app-frame").contentWindow;
                iframe.postMessage(postMessageStructure, origin);
            }
        },
        false
    );
</script>

Use JSON Web Token

If you are using JSON Web Token (JWT) instead of an API token for authentication edit your event data payload in the following way:

event: {
    name: "setApiToken",
    data: {
        token: "<jwt_token_value>",
        type: "jwt",
        secondsBeforeTokenExpirationToEmitReminder: 60
    }
}

When the token is 60 seconds from expiring, the apiTokenIsAboutToExpire event is emitted to notify you and give you a chance to post a fresh token. Note that 60 seconds is the default value, but you can change it.

We recommend you check out the Create JWK and JWT in JavaScript to get started on handling JWTs inside JavaScript.

Example of Authentication Using Injected JWT

This is a modified example of the API token injection example shown above that has been modified to better suit the JWT use case:

<iframe
        title="Embed GD Application"
        id="embedded-app-frame"
        src="<host_url>/analyze/embedded/#/<workspace_id>/<visualization_id>?apiTokenAuthentication=true"
        width="1300"
        height="800"
></iframe>
<script>
    console.log("Setup parent frame message listener")

    window.addEventListener(
        "message",
        function (event) {
            console.log("Post message received", event);

            const eventName = event.data.gdc?.event.name;

            // Send new token when embedded application ask for it for the first time and then subsequently
            // each 60 seconds before the previous token expires. 
            if (eventName === "listeningForApiToken" || eventName === "apiTokenIsAboutToExpire") {
                // Fetch token from JWT generator endpoint, for example Node.JS Express application.
                // The application must ensure that the call is authenticated, for example via request cookie
                // or through SSO
                fetch(`/api/jwt-generator?user=john.doe`, {
                    method: "GET"
                }).then(function (response) {
                    if (response.ok) {
                        return response.json();
                    }
                    throw response;
                }).then(function (data) {
                    const postMessageStructure = {
                        gdc: {
                            product: "analyticalDesigner",
                            event: {
                                name: "setApiToken",
                                data: {
                                    token: data.jwt, // example expects the response is {"jwt": "<jwt_value>"}
                                    type: "jwt",
                                    secondsBeforeTokenExpirationToEmitReminder: 60,
                                }
                            }
                        }
                    };

                    console.log("Sending JWT to embedded window");

                    const origin = "*";
                    const iframe = document.getElementById("embedded-app-frame").contentWindow;
                    iframe.postMessage(postMessageStructure, origin);
                });
            }
        },
        false
    );
</script>

PostMessages

When you embed the Analytical Designer, you can set up receiving messages from the Analytical Designer to your application.

Events

The following events are supported:

insightOpened

Triggered when a visualization is opened within the analytical designer.

{
    "gdc": {
        "product": "analyticalDesigner",
        "event": {
            "name": "insightOpened",
            "data" : {...}
            "contextId": "context123"
        }
    }
}

insightChanged

Triggered when the content of a visualization is modified within the analytical designer.

{
    "gdc": {
        "product": "analyticalDesigner",
        "event": {
            "name": "insightChanged",
            "data" : {...},
            "contextId": "context123"
        }
    }
}

insightRendered

Triggered when a visualization is fully rendered in the analytical designer.

{
    "gdc": {
        "product": "analyticalDesigner",
        "event": {
            "name": "insightRendered",
            "data" : {...},
            "contextId": "context123"
        }
    }
}

setFilterContextFinished

Triggered when the process of setting the filter context is completed in the analytical designer.

{
    "gdc": {
        "product": "analyticalDesigner",
        "event": {
            "name": "setFilterContextFinished",
            "contextId": "context123"
        }
    }
}

filterContextChanged

Triggered when the filter context is modified within the analytical designer.

{
    "gdc": {
        "product": "analyticalDesigner",
        "event": {
            "name": "filterContextChanged",
            "data": {
                "filters": [
                    {
                        "relativeDateFilter": {
                            "dataSet": {
                                "identifier": "identifier 123",
                                "type": "dataSet"
                            },
                            "granularity": "GDC.time.date",
                            "from": -6,
                            "to": 0
                        },
                        "localIdentifier": "id123"
                    }
                ]
            },
            "contextId": "context123"
        }
    }
}

Commands

The following commands are supported:

setApiToken

Set the API token you want to use for authentication. See the Example in the parent article.

{
    "gdc": {
        "product": "analyticalDesigner",
        "event": {
            "name": "setApiToken",
            "contextId": "<context_id>",
            "data": {
                "token": "<api_token_value>"
            }
        }
    }
}

undo

Reverts the most recent change made to the visualization.

{
    "gdc": {
        "product": "analyticalDesigner",
        "event": {
            "name": "undo",
            "contextId": "<context_id>"
        }
    }
}

redo

Reapplies the most recently undone edit to the visualization.

{
    "gdc": {
        "product": "analyticalDesigner",
        "event": {
            "name": "redo",
            "contextId": "<context_id>"
        }
    }
}

clear

Removes all items and information from the visualization.

{
    "gdc": {
        "product": "analyticalDesigner",
        "event": {
            "name": "clear",
            "contextId": "<context_id>"
        }
    }
}

clearInsight

Removes the following items from the insight:

  • Attributes
  • Facts
  • Metrics
  • Filters
{
    "gdc": {
        "product": "analyticalDesigner",
        "event": {
            "name": "clearInsight",
            "contextId": "<context_id>"
        }
    }
}

openInsight

Opens an existing visualization.

{
   "gdc": {
        "product": "analyticalDesigner",
        "event": {
            "name": "openInsight",
            "data": {
                "reportId": "<reportId>",
                "projectId": "<projectId>"
            },
            "contextId": "<context_id>"
        }
    }
}

setFilterContext

Applies a set of filters to the embedded Analytical Designer. You can define, one or more filters in the filter definition.

Example: Attribute filter with all values

{
    "gdc": {
        "product": "analyticalDesigner",
        "event": {
            "name": "setFilterContext",
            "data": {
                "filters": [
                    {
                        "negativeAttributeFilter": {
                            "displayForm": {
                                "identifier": "county_name"
                            },
                            "notIn":[]
                        }
                    }
                ]
            },
            "contextId": "<context_id>"
        }
    }
}

Example: Negative attribute filter

{
    "gdc": {
        "product": "analyticalDesigner",
        "event": {
            "name": "setFilterContext",
            "data": {
                "filters": [
                    {
                        "positiveAttributeFilter": {
                            "displayForm": {
                                "identifier": "ls__id__nm_stagename"
                            },
                            "in": ["Closed Lost","Closed Won","Conviction","Discovery"]
                        }
                    }
                ]
            },
            "contextId": "<context_id>"
        }
    }
}

Example: Relative date filter

{
    "gdc": {
        "product": "analyticalDesigner",
        "event": {
            "name": "setFilterContext",
            "data": {
                "filters": [
                    {
                        "relativeDateFilter": {
                            "dataSet": {
                                "identifier": "dt_closedate_timestamp", 
                                "type": "dataSet"
                            },
                            "granularity": "GDC.time.year",
                            "from": -8,
                            "to": 0
                        }
                    }
                ]
            },
            "contextId": "<context_id>"
        }
    }
}

Example: Absolute date filter

{
    "gdc": {
        "product": "analyticalDesigner",
        "event": {
            "name": "setFilterContext",
            "data": {
                "filters": [
                    {
                        "absoluteDateFilter": {
                            "dataSet": {
                                "identifier": "dt_closedate_timestamp", "type": "dataSet"
                            },
                            "from": "2010-05-24",
                            "to": "2010-05-24"
                        }
                    }
                ]
            },
            "contextId": "<context_id>"
        }
    }
}

Example: Ranking filter

{
    "gdc": {
        "product": "analyticalDesigner",
        "event": {
            "name": "setFilterContext",
            "data": {
                "filters": [
                    {
                        "rankingFilter": {
                            "measure": {
                                "localIdentifier": "{local_identifier}"
                            },
                            "operator": "TOP",
                            "value": 1
                        }
                    }
                ]
            },
            "contextId": "<context_id>"
        }
    }
}

removeFilterContext

Removes filters from the embedded analytical designer.

{
    "gdc": {
        "product": "analyticalDesigner",
        "event": {
            "name": "removeFilterContext",
            "data": {
                "filters": [
                    // attribute filter
                    {
                        "displayForm": {
                            "identifier": "identifier123"
                        }
                    },
                    // date filter
                    {
                        "dataSet": {
                            "identifier": "identifier123"
                        }
                    },
                  // Ranking filter
                    {
                        "removeRankingFilter": {}
                    }
                ],
            },
            "contextId": "<context_id>"
        }
    }
}