Skip to main content

Embedding Marketplace

The video above walks through the steps to embed Prismatic in your app, starting from a blank React app.

Embed the integration marketplace

You can embed the Integration Marketplace into your application with just a few lines of code, giving your customers a native integration deployment experience. This article details how to embed Prismatic's integration marketplace into your application.

For information on how to install the embedded SDK and authenticate customer users, see Installing Embedded SDK

Once a user has been authenticated, you can display the integration marketplace to them using the prismatic.showMarketplace() function. The showMarketplace() function takes three optional arguments:

  • usePopover is a boolean that determines if the marketplace should display as a popover.
    By default, the screen is injected as an iframe into an existing DOM element.
  • selector identifies which element in the DOM to inject the iframe into when usePopover is false.
  • theme can override custom theming default behavior, and can be set to "LIGHT" or "DARK" mode.

iframe injection method

When showPopover is set to false, an iframe HTML element is injected into an element that you select with the selector argument. The iframe contains the integration marketplace.

For example, if you have a section of your app that reads:

<div id="integration-marketplace-placeholder" style="height:100%">
Loading...
</div>

You can inject the integration marketplace iframe into that div, replacing the "Loading..." text, by invoking:

prismatic.showMarketplace({
selector: `#integration-marketplace-placeholder`,
usePopover: false,
});

The result is that the integration marketplace appears to be a portion of the rest of your application:

Prismatic integration marketplace embedded in your app

Note: at this point marketplace has not been themed to match your app. To match your app branding, see Theming Embedded Marketplace.

For an example of the iframe injection method, see GitHub.

Popover method

If you elect to set usePopover to true, a popover will be opened containing the integration marketplace:

prismatic.showMarketplace({
usePopover: true,
});
Enable popover for Prismatic embedded marketplace

Filtering integrations

You can choose to show a subset of your integrations by applying filters to your showMarketplace() invocation.

Simple integration filters

You can filter your integrations by a single category or label (or both). If you filter by both, integrations will appear only if they match both category and label.

For example, if you would like to show only integrations with the category "ERP" and the label "enterprise" in an embedded marketplace, you can issue this invocation:

Filter by category and label
prismatic.showMarketplace({
selector: `#my-div-id`,
usePopover: false,
filters: {
marketplace: {
category: "ERP",
label: "enterprise",
},
},
});

Advanced integration filters

You can use a filterQuery to perform more advanced logic when filtering integrations. You can query for integrations given the integration's name, labels or category. The following operators are at your disposal:

  • TermOperator.equal checks if the first term is equal to the second term and can be used for name and category. For example, to show only the integration named "Dropbox" enter:

    prismatic.showMarketplace({
    filters: {
    marketplace: {
    filterQuery: [TermOperator.equal, "name", "Dropbox"],
    },
    },
    });
  • TermOperator.notEqual checks if the first term is not equal to the second term and can be used for name and category. For example, to show all integrations except those with the category "ERP" use:

    prismatic.showMarketplace({
    filters: {
    marketplace: {
    filterQuery: [TermOperator.notEqual, "category", "ERP"],
    },
    },
    });
  • TermOperator.in is used to check if the integration's labels include a specific label. For example, if you want to show integrations with a "paid" label, use:

    prismatic.showMarketplace({
    filters: {
    marketplace: {
    filterQuery: [TermOperator.in, "labels", "paid"],
    },
    },
    });
  • TermOperator.notIn will show integrations that do not have certain labels.

  • TermOperator.startsWith checks if a name or category begins with a certain string. For example, to find all integrations that start with "Algolia" use:

    prismatic.showMarketplace({
    filters: {
    marketplace: {
    filterQuery: [TermOperator.startsWith, "name", "Algolia"],
    },
    },
    });

    That will match integrations with names like Algolia - Dropbox or Algolia - SFTP.

  • TermOperator.doesNotStartWith returns integrations with name or category that does not start with a certain string.

  • TermOperator.endsWith returns integrations with name or category that ends with a certain string.

  • TermOperator.doesNotEndWith returns integrations with name or category that does not end with a certain string.

Several conditionals can be applied in unison with and and or logic. For example, if you would like to show all integrations that have a category "ERP" and label "paid", and would also like the Dropbox and Slack integrations, a filter could look like:

import prismatic, {
BooleanOperator,
TermOperator,
} from "@prismatic-io/embedded";

prismatic.showMarketplace({
filters: {
marketplace: {
filterQuery: [
BooleanOperator.or,
[
BooleanOperator.and,
[TermOperator.equal, "category", "ERP"],
[TermOperator.in, "labels", "paid"],
],
[TermOperator.equal, "name", "Dropbox"],
[TermOperator.equal, "name", "Slack"],
],
},
},
});

Configure a specific integration

If you'd like to use your own UI elements (a button, div, hyperlink, etc) for selecting an integration to deploy, you can.

Invoke the prismatic.configureInstance() function from your UI element to display a configuration screen for a specific integration by passing in the name of the integration as integrationName. You can pass in other display information (like usePopover and selector) as you would with the iframe injection and popover methods described above.

You can also pass in an optional skipRedirectOnRemove boolean, which defaults to false. This determines if your user should be redirected to the list of integrations upon removing an integration. If you are embedding marketplace, you probably want to keep this value false. If you're wrapping our API and handling displaying of integrations yourself, you might want this to be true.

For example, if you would like your "Salesforce" integration to appear when someone clicks one of your buttons, you could invoke configureInstance like this:

const deploySalesforce = () => {
prismatic.configureInstance({
integrationName: "Salesforce",
skipRedirectOnRemove: false,
usePopover: true,
});
};

<Button onClick={deploySalesforce}>Configure Salesforce Integration</Button>;

For an example of rendering a custom UI for marketplace, and opening the configuration screen for a specific integration with prismatic.configureInstance(), see GitHub.

Listening to Marketplace events

The embedded marketplace emits custom JavaScript events when certain things happen:

  • An INSTANCE_CREATED event is emitted the first time an integration's configuration screen is opened.
  • An INSTANCE_CONFIGURATION_OPENED event is emitted when an instance configuration screen is opened.
  • An INSTANCE_CONFIGURATION_LOADED event is emitted when an instance configuration screen has loaded. This is a good event to hook into if you want to programmatically set config variables.
  • An INSTANCE_CONFIGURATION_PAGE_LOADED event is emitted when an instance configuration screen has moved from one page to another.
  • An INSTANCE_CONFIGURATION_CLOSED event is emitted when an instance configuration screen is closed (regardless of if configuration was completed or not).
  • An INSTANCE_DEPLOYED event is emitted when an instance has been configured and enabled for a customer.
  • An INSTANCE_DELETED event is emitted when an integration has been deactivated (the instance has been deleted).

You can subscribe to these events so your app can take additional steps when an instance has been created, configured, deleted, etc. All events return data structured similar to this (except for INSTANCE_CONFIGURATION_LOADED, which returns additional data):

{
"event": "INSTANCE_CONFIGURATION_OPENED",
"data": {
"customerId": "Q3VzdG9tZXI6OThiMjU3MDUtZmMzNC00NWYwLTk0ZDItODA0ZjFkYzEyYTZk",
"customerName": "Smith Rockets",
"instanceId": "SW5zdGFuY2U6YzJlYTliZjEtY2Y3MS00NTg1LTk2MjMtYjZhNDAxYjQyNWRm",
"instanceName": "Salesforce",
"integrationName": "Salesforce",
"integrationVersionNumber": 18,
"readOnly": false
}
}

In this example we log out the name of the customer and what integration they opened:

import { PrismaticMessageEvent } from "@prismatic-io/embedded";

window.addEventListener("message", (event) => {
// Check if the message event is of type INSTANCE_CONFIGURATION_OPENED
if (
event.data.event === PrismaticMessageEvent.INSTANCE_CONFIGURATION_OPENED
) {
// Grab some data
const { customerName, integrationName } = event.data.data;
// Log out the customer and integration name. You can replace this with whatever data or helper functions you want
console.log(
`${customerName} opened the configuration page for ${integrationName}`,
);
}
});

Similar event listeners can be added for when an instance configuration page is closed or loads, or an instance is initially created or deleted.

User-level configuration Marketplace events

If user-level configuration is enabled for an integration, you will see the following marketplace events:

  • A USER_CONFIGURATION_OPENED event is emitted when a ULC configuration screen is opened.
  • A USER_CONFIGURATION_LOADED event is emitted when a ULC configuration screen has loaded. This is a good event to hook into if you want to programmatically set config variables.
  • A USER_CONFIGURATION_PAGE_LOADED event is emitted when aa ULC configuration screen has moved from one page to another.
  • A USER_CONFIGURATION_CLOSED event is emitted when a ULC configuration screen is closed (regardless of if configuration was completed or not).
  • A USER_CONFIGURATION_DEPLOYED event is emitted when a ULC configuration is completed.
  • A USER_CONFIGURATION_DELETED event is emitted when a ULC configuration is deleted.

For all of these events, the event's data property will look like this:

{
"event": "USER_CONFIGURATION_LOADED",
"data": {
"customerId": "Q3VzdG9tZXI6ZjYxMzY4MzItMzYxYi00NmI3LTlmMmItN2ZkNTc3YzY1YTg1",
"customerName": "Smith Real Estate",
"instanceId": "SW5zdGFuY2U6N2I1MjFiNzItYzllNS00YjkwLWIzZGEtZTY4OTY5OWU2ZjBl",
"instanceName": "Dropbox",
"integrationName": "Dropbox",
"integrationVersionNumber": 9,
"userConfigId": "VXNlckxldmVsQ29uZmlnOjI0NDU5MjA2LWQxNGUtNDRhMy04NWE4LTJjMzgwMzg2Y2NmZg==",
"userEmail": "2E52B7CB-071B-4EA2-8E9D-F64910EBDBB1",
"userId": "VXNlcjpmYjc4YzE1OS1kOWMwLTQxMDctYjIyNC0zYmNhMDFlOTQ5NzY=",
"userLevelConfigVariables": {
"Dropbox Connection": {
"status": "ACTIVE"
}
},
"readOnly": false,
"userName": "Phil Embedmonson"
}
}

Dynamically setting config variables in marketplace

You can programmatically set values for your customers' config variables by leveraging marketplace events. This is handy if you know some value (an API key, endpoint, etc), and would like to set a config variable on your customer's behalf (so they don't need to look up the values themselves).

When your app receives an INSTANCE_CONFIGURATION_LOADED event message (or USER_CONFIGURATION_LOADED for ULC), the message's payload contains the properties listed above, plus current config variable values.

You can inspect that event's data, and conditionally set values for some config variables using the prismatic.setConfigVars() function. Let's look at the event message, and how to respond to it with some config variable values:

Here's what the INSTANCE_CONFIGURATION_LOADED payload looks like. The event message's .data.configVars property contains all currently set config variables and their values:

Example INSTANCE_CONFIGURATION_LOADED event payload
{
"event": "INSTANCE_CONFIGURATION_LOADED",
"data": {
"instanceId": "SW5zdGFuY2U6ZTE4NTNkYWItZjJhMi00OGIyLTk1ZWItODRjYzQ3YzRiMzc4",
"instanceName": "Test Embedded config vars",
"integrationName": "Test Embedded config vars",
"integrationVersionNumber": 1,
"customerId": "Q3VzdG9tZXI6OThiMjU3MDUtZmMzNC00NWYwLTk0ZDItODA0ZjFkYzEyYTZk",
"customerName": "Smith Rockets",
"readOnly": false,
"configVars": {
"Acme Connection": {
"inputs": {
"username": { "value": "" },
"password": { "value": "" }
},
"status": "PENDING"
},
"My Key/Value List": {
"value": [],
"collectionType": "keyvaluelist",
"codeLanguage": null,
"dataType": "string",
"pickList": null,
"scheduleType": null,
"timeZone": null
},
"My String": {
"value": "",
"collectionType": null,
"codeLanguage": null,
"dataType": "string",
"pickList": null,
"scheduleType": null,
"timeZone": null
},
"My List": {
"value": [],
"collectionType": "valuelist",
"codeLanguage": null,
"dataType": "string",
"pickList": null,
"scheduleType": null,
"timeZone": null
},
"My String With Default": {
"value": "Some Default",
"collectionType": null,
"codeLanguage": null,
"dataType": "string",
"pickList": null,
"scheduleType": null,
"timeZone": null
},
"My List With Default": {
"value": ["Foo1", "Foo2"],
"collectionType": "valuelist",
"codeLanguage": null,
"dataType": "string",
"pickList": null,
"scheduleType": null,
"timeZone": null
},
"My Picklist": {
"value": "",
"collectionType": null,
"codeLanguage": null,
"dataType": "picklist",
"pickList": ["Foo", "Bar", "Baz"],
"scheduleType": null,
"timeZone": null
},
"My Boolean": {
"value": false,
"collectionType": null,
"codeLanguage": null,
"dataType": "boolean",
"pickList": null,
"scheduleType": null,
"timeZone": null
}
}
}
}

The getMessageIframe helper function

Your app needs to know which iframe to send a setConfigVars message to. Your app might have multiple iframes, and potentially multiple instances of the embedded marketplace on a single page.

The getMessageIframe function helps to identify which iframe generated the INSTANCE_CONFIGURATION_LOADED event.

If you would like to send a setConfigVars message to a specific iframe, you can instead pass a selector property to the setConfigVars function (like you did for prismatic.showMarketplace()):

setConfigVars message by selector
prismatic.setConfigVars({
selector: "#my-marketplace-container",
configVars: {
"My Config Var Name": { value: "My config var value" },
},
});

Hiding UI elements in marketplace

You can optionally hide the Back to Marketplace link, some tabs from the instance screen, and elements of the instance configuration wizard. This is useful if you want to prevent your customers from running tests from the Test tab or reconfiguring alert monitors for themselves.

To disable certain UI elements, add a screenConfiguration block to your prismatic.showMarketplace() or prismatic.configureInstance() invocations:

Hide the 'back' link and 'monitors' and 'test' tabs
prismatic.showMarketplace({
selector: `#${id}`,
usePopover: false,
theme: "LIGHT",
screenConfiguration: {
instance: {
hideBackToMarketplace: true,
hideTabs: ["Monitors", "Test"],
},
configurationWizard: {
hideSidebar: true,
isInModal: true,
triggerDetailsConfiguration: "hidden",
},
marketplace: {
hideSearch: true,
hideActiveIntegrationsFilter: true,
},
},
});
  • instance.hideBackToMarketplace determines whether or not to hide the Back to Marketplace link in the instance configuration screen and defaults to false.
  • instance.hideTabs determines which tabs to hide from the instance configuration screen. You can choose from the Test, Executions, Monitors or Logs tabs. No tabs are hidden by default.
  • configurationWizard.hideSidebar hides the left-hand sidebar from the configuration wizard (the config wizard page titles and numbers).
  • configurationWizard.isInModal affects if the config wizard should appear over the current page in a modal. When set to true, it's assumed that your embedded marketplace is already in a modal, (and since a modal-in-a-modal isn't the best look), opens the config wizard to fill its containing <div>.
  • configurationWizard.triggerDetailsConfiguration determines if and how trigger details are shown in the config wizard. Your options are hidden to hide trigger details completely, default to include the element, but collapse them, or default-open to include the element and have it expanded. Endpoint details may also be hidden if they are not configured to be Secured by Customer (see Endpoint Configuration).
  • marketplace.hideSearch will hide the search bar in the marketplace.
  • marketplace.hideActiveIntegrationsFilter will hide top-right filter for active integrations in the marketplace.

If you would like to apply your preferences globally (in the case that you have multiple invocations showMarketplace() and configureInstance()), you can configure settings when you run prismatic.init():

Hide UI elements globally
prismatic.init({
screenConfiguration: {
instance: {
hideBackToMarketplace: true,
hideTabs: ["Test", "Monitors"],
},
},
});

Screen configuration settings in prismatic.init() can be overridden within a specific showMarketplace() or configureInstance() invocation. hideTabs properties are not merged if yo do this - the screenConfiguration settings in showMarketplace / configureInstance completely override the default settings in init.

Integration configuration detail screen

The embedded SDK configuration allows you to fine-tune the user experience for accessing the integration configuration details screen. It includes the ability to prevent a marketplace user from accessing the detail screen. This is useful if you do not want your customer to access the Test, Executions, Monitors or Logs functionality.

  • allow-details Will redirect the marketplace user back to the marketplace listing after the user finishes the configuration wizard. When a user clicks on an integration from the marketplace listing, they will see a summary of the integration including the integration status. The user can manage the instances from the overflow menu at the bottom. "View Details" will open the full details integration screen. You can hide some UI elements of this page. This is the default behavior if no configuration is provided, starting in SDK version 2.0.0.
  • disallow-details Will provide the same experience as the allow-details option described above. However, users will not have access to the details option from the overflow menu.
  • always-show-details Will redirect the marketplace user to the full integration details screen after the integration has been configured or when an instance is selected from the marketplace listing.
Inline configuration experience that allows marketplace users to access integration config details
prismatic.showMarketplace({
selector: `#my-div`,
screenConfiguration: {
marketplace: {
configuration: "allow-details",
},
},
});

Showing all instances in marketplace

Sometimes you will have an integration that you would like to deploy to a specific customer via Marketplace, but you don't want to make it generally available to all customers. To accomplish that, deploy an unconfigured instance of the integration to your customer as an organization user. Then, set the screenConfiguration.marketplace.includeActiveIntegrations marketplace option to true to show instances that are enabled for a customer (even if the integration is not in marketplace):

Show all instances in marketplace
prismatic.showMarketplace({
selector: `#my-div`,
screenConfiguration: {
marketplace: {
includeActiveIntegrations: true,
},
},
});
filters take precedence over includeActiveIntegrations by default

Note that if you have filters enabled, the includeActiveIntegrations option will not override the filters. By default, active integrations that are deployed to a customer must match the filters you specify in order to be shown.

If you would like to show all active integrations, regardless of filters, in addition to the marketplace integrations that match your filters, set the includeActiveIntegrations option to true, and set an additional property strictMatchFilterQuery to false.

Multiple instances of one integration in Marketplace

By default customer users can enable a single instance of an integration through embedded marketplace. There are situations, though, where you want customers to be able to deploy multiple instances of an integration. For example, your customers may have multiple Shopify stores, and require a separate instance of your Shopify integration for each store.

Enabling customers to deploy multiple instances of an integration is configured on a per-integration basis. From the marketplace configuration screen or the marketplace drawer in the integration designer, enable the Allow Multiple Instances toggle.

Allow multiple instances toggle in marketplace drawer

Embedded customer users who select your integration will be able to view existing instances of the integration that are enabled, and will have the option to add additional instances of the integration.

Multiple instances in embedded marketplace

Customers will see a similar view if you have enabled multiple instances of an integration for them.

Custom marketplace UI

The embedded marketplace listview screen is presented as an iframe. If you would prefer to present marketplace integrations in your own custom UI elements, you can. This is helpful if you build some integrations in Prismatic, and others outside of Prismatic - you can display both together using the same UI elements.

To fetch a list of marketplace integrations, use your customer's signed JWT to query the Prismatic API for marketplaceIntegrations. An example of a query you can issue is available in our example embedded app. This query will return an array of integrations that have been added to marketplace. You can map that array to whatever custom UI elements you'd like.