Skip to content

Integration levels

When you create an integration with the Netlify SDK, the integration can perform logic on the team level, site level, or both. To make informed decisions about your architecture, consider what level users will enable and authenticate your integration on.

Available integration levels

Users can enable, disable, and use integrations on different levels:

  • Site level: users can only enable this level of integration on a site. For example:
  • Team level: users can only enable this level of integration on a team. For example:
    • An integration with a connector that allows users to connect to and sync data from a custom data source to Netlify Connect.
    • An integration that sets specific environment variables that can be used across sites. Note that only certain Netlify customer plans support team-level environment variables.
  • Team and site level: users enable this level of integration on a team first, and then enable it on a site. For example:
    • An integration that sets a team-based configuration or environment variable that is used on a site level in a build event handler. For example, an API key shared across all sites in a team. The integration can also set site-level configurations.

Specify the integration level

You set the integration level when you register and publish your integration.

Netlify automatically prompts you for the level when you publish a private integration, and you need to provide this information to the Netlify team when you publish a partner integration.

Add logic for integrations that run on both team and site level

Along with specifying the integration level when you register your integration, integrations that work on both the team and site level require additional logic in the integration code. You need to ensure your integration includes separate team and site level logic for certain functionalities.

To confirm whether certain logic is running on the site or team level, your code can include a check for a siteId. If the siteId is available, the integration is running on the site level.

The following sections outline some examples of when your integration may want to specify different logic depending on the integration level.

Build Event Handlers

If your integration includes a build event handler, the integration must include code to enable the handler when the user enables your integration.

Since Build Event Handlers run on sites, you should enable the handler only when the integration is enabled for a site. The onEnable method runs on both the team and site level, so it’s important to check that a siteId is available before enabling the handler.

// src/index.ts
integration.onEnable(async (_, { siteId, client }) => {
  // Build event handlers are disabled by default, so we need to
  // enable them when the integration is enabled.

  // The onEnable method is used when enabling for both a team and site.
  // This is why we check if we have a siteId before we try to enable
  // the build event handler.
  siteId && (await client.enableBuildEventHandlers(siteId));

  return {
    statusCode: 200,
  };
});

When the user disables your integration on a site level, Netlify automatically disables the build event handler for you. You don’t need to write logic for this step.

Integration UI

When creating an Integration UI for integrations that run on both the team and site level, you might want to customize the UI for each level. To show or hide specific parts of your Integration UI based on the level, check if you have a siteId available.

// src/ui/index.ts

import { NetlifyIntegrationUI } from "@netlify/sdk";

const integrationUI = new NetlifyIntegrationUI("ABC Integration");
const surface = integrationUI.addSurface("integrations-settings");
const route = surface.addRoute("/");

route.onLoad(async (surfaceState) => {
  const {
    picker,
    integrationContext: { siteId },
  } = surfaceState;

  const teamConfigCard = picker?.getElementById("team-config-card");
  const siteConfigCard = picker?.getElementById("site-config-card");

  if (siteId) {
    siteConfigCard.display = "visible";
    teamConfigCard.display = "hidden";
  }
});

route.addCard(
  {
    title: "Team Config",
    id: "team-config-card",
    display: "visible",
  },

  (card) => {
    card.addText({
      value: "Some config text for a team level",
    });
  }
);

route.addCard(
  {
    title: "Site Config",
    id: "site-config-card",
    display: "hidden",
  },

  (card) => {
    card.addText({
      value: "Some config text for a site level",
    });
  }
);

export { integrationUI };

API Handlers

If you call an API handler through the Integration UI and want the API handler to perform different logic based on whether the Integration UI is accessed on the site or team level, check if a siteId is available.

// src/index.ts
import { NetlifyIntegration } from "@netlify/sdk";

const integration = new NetlifyIntegration();

integration.addApiHandler("cool-function", async (event, context) => {
  const body = JSON.parse(event.body);
  const { client } = context;
  const { siteId } = body;

  if (siteId) {
    // Do something cool here for the site
  }

  return {
    statusCode: 200,
  };
});