---
title: "Hook into Netlify’s Build Events with Private Integrations"
description: "Simplify and enhance team builds with Build Event Handlers. Detect broken links pre-deployment, create private integrations, and enable them effortlessly."
source: "https://www.netlify.com/blog/hook-into-build-events-with-private-integrations/"
last_updated: "2026-07-11T04:43:20.000Z"
---
Have you slowly seen your team’s build process grow into a complex monster with configuration files the size of Mount Doom? Don’t worry, we’re here to help! Netlify Build Event Handlers can help make these processes more accessible for you and your team. Setting it up is a breeze — create a Private Integration once, and enable it for any site within your team. Did I mention it uses TypeScript? Throw out unnecessary complexity and join me in building next-generation integrations on Netlify.

## What is a Build Event Handler?

Build Event Handlers open up a world of possibility by seamlessly integrating into the Netlify site building process and enhancing what Netlify builds can achieve. You can do things like perform post-build checks for broken links on your site, generate content such as sitemaps, RSS feeds, search indexes, and so much more. The imaginative digital sky is the limit!

As an example, I’m going to show you how you can build a private integration that checks for broken links on a site _after_ building it but _before_ deploying it. If it finds a broken link, it will automatically cancel the deploy.

## Creating the basis for your private integration

You’ll be using the [Netlify SDK](https://sdk.netlify.com/get-started/introduction/) to create your private integration. In your terminal, navigate to the folder where you want to make your integration and type: `pnpm create @netlify/sdk@latest`.

You will be prompted with some questions that help guide you in creating your new integration. Feel free to choose your own package manager, but make sure to go with the following answers:

```
? Where do you want to create the integration? link-checker-integration? What is the slug of the integration? (e.g. my-integration) link-checker-integration? What level will this integration be installed on? site? Summarize what your integration does. This will be shown on the integration's cardon the Integrations page. This integration checks your build for any broken links? Which boilerplate should be included? build? Which package manager do you want to use? pnpm? Select your permission scopes site:read? Do you want to link a Netlify site to your integration? This will help you test your integration and will be used to host your integration. skip
```

Then, you can navigate to the directory it created for you by typing `cd link-checker-integration`. If you run `ls` you should be seeing something similar to this:

```
├── integration.yaml├── netlify.toml├── package.json├── pnpm-lock.yaml├── src│   └── index.ts└── tsconfig.json
```

## Your Build Event Handler boilerplate

The SDK already made a few files for you! Let’s open up `src/index.ts` to see what your Build Event Handler boilerplate looks like:

```
// Documentation: https://sdk.netlify.comimport { NetlifyIntegration } from "@netlify/sdk";
const integration = new NetlifyIntegration();
integration.onEnable(async (_, { teamId, siteId, client }) => {  // Build event handlers are disabled by default, so we need to  // enable them when the integration is enabled.
  siteId && await client.enableBuildEventHandlers(siteId);
  return {    statusCode: 200,  };});
integration.addBuildEventHandler("onPreBuild", () => {  console.log("Hello there.");});
export { integration };
```

There are a [number of events](https://sdk.netlify.com/build-event-handlers/hook-into-events/) in the build pipeline you can hook into if you want. But for this example let’s change the `onPreBuild` function to `onPostBuild`. Then make the function async and grab some function parameters like `constants` and `utils`. Your `addBuildEventHandler` method should look something like this:

```
integration.addBuildEventHandler('onPostBuild', async ({ constants, utils }) => {  console.log("Hello there.");});
```

## Adding linkinator

To add the functionality of scanning a site’s build folder for any broken links we will use a package called [linkinator](https://github.com/JustinBeckwith/linkinator#readme), go ahead and run `pnpm install linkinator`.

Make sure to import the `LinkChecker` class from the package and create a new instance of it. Then use `constants.PUBLISH_DIR` to pass the folder that should be checked for any broken links. In this case I assume it will be the `PUBLISH_DIR`. You can set up your Build Event Handler in a way that, if the package finds any broken links, the deploy is cancelled! This is done by leveraging `utils.build.failBuild`.

This is what the code should look like:

```
// Documentation: https://sdk.netlify.comimport { NetlifyIntegration } from '@netlify/sdk';import { LinkChecker } from 'linkinator';
const integration = new NetlifyIntegration();
integration.onEnable(async (_, { teamId, siteId, client }) => {  // Build event handlers are disabled by default, so we need to  // enable them when the integration is enabled.
  siteId && (await client.enableBuildEventHandlers(siteId));
  return {    statusCode: 200,  };});
integration.addBuildEventHandler(  'onPostBuild',  async ({ constants, utils }) => {    const checker = new LinkChecker();    // Pass the PUBLISH_DIR that the site was built in    const result = await checker.check({      path: constants.PUBLISH_DIR,    });
    // Log wether we passed or failed!    console.log(result.passed ? 'PASSED :D' : 'FAILED :(');
    if (!result.passed) {      // The list of checked links, and the pass/fail      const brokeLinksCount = result.links.filter(        (x: { state: string }) => x.state === 'BROKEN'      );      console.log(`Detected ${brokeLinksCount.length} broken links.`);
      // Show the list of scanned links and their results      console.log(result);      // Fail the build and cancel the deploy if there are broken links      utils.build.failBuild('There are broken links, fix them first!');    }  });
export { integration };
```

That’s it! You are now ready to deploy your integration.

## Deploy your integration

Alright, let’s get your integration out there for your team to use! First, make sure you commit the latest changes to your repository and publish it to your Git provider, for example [GitHub](https://docs.github.com/en/migrations/importing-source-code/using-the-command-line-to-import-source-code/adding-locally-hosted-code-to-github). This way we can leverage Netlify’s [continuous deployment](https://docs.netlify.com/site-deploys/create-deploys/#deploy-with-git). When you’re done with that, use the [Netlify CLI](https://docs.netlify.com/cli/get-started/#installation) to run `netlify init` in your terminal and answer the questions:

```
? What would you like to do? Create & configure a new site? Team: {your team name}? Site name (leave blank for a random name; you can change it later): {keep blank}? Your build command (hugo build/yarn run build/etc): netlify-integration build -a? Directory to deploy (blank for current dir): .ntli/site/static
```

Alright, you’re done! In your terminal, you should see an Admin URL. If you click it, it will take you to your admin panel in Netlify.

## Creating a Private Integration

Now that we’ve deployed your code, we’re going to officially create a Private Integration out of it! In the Netlify UI, navigate to “integrations”. Once you’re there, select “Create a private integration” and fill in the form. You can find [detailed information on the fields you see here](https://sdk.netlify.com/publish/private-integrations/#integration-metadata), but I’ll highlight a few special ones as well:

-   **Netlify integration site:** select the name of the integration you have just deployed in the previous step!
-   **************************************Integration level:************************************** this integration will only work on a site level, so choose site.
-   **Permission scopes:** we only need site “read” permissions for this integration.

Smash that “create” button! You’re done!

## Enabling your integration for your team’s sites

Now that your private integration has been deployed, we’re going to use it on one of your sites! Either find a site in your Netlify team that you want to use, or use the one [I’ve made for you](https://github.com/netlify/linkchecker-test-site) so you can test this integration out as soon as possible! You can deploy it with this button:

[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/linkchecker-test-site)

Once you’ve found a site you want to try your integration on, navigate to that site in the Netlify UI, and then go to “integrations”. Once you’re there, select the private integrations category. In that list you should be able to see a card with the name of the integration you just created. Enable that integration by selecting the “enable” button.

If you now run a new deploy on the site you’ve enabled your integration on, you should be able to see logs from your integration in the ‘build’ section of your deploy logs! Congratulations, you did it!

## Next steps and making your integrations public

If you just want to try out this integration, use the button below to deploy it to your Netlify Team. And don’t forget to check out the [template repository](https://github.com/netlify/sdk-build-event-handler-link-checker-template).

[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/integration/start/deploy?repository=https://github.com/netlify/sdk-build-event-handler-link-checker-template&integrationName=link-checker-integration&integrationSlug=link-checker-integration&integrationDescription=Check%20your%20sites%20links&scopes=site:read&integrationLevel=site)

You can use this new integration on all of the sites you have within your Netlify Team! Learn more about [building integrations on Netlify](https://sdk.netlify.com/get-started/introduction/), or [how to create a partner integration on Netlify](https://sdk.netlify.com/publish/partner-integrations/).

Happy coding on Netlify!

### Share

-   [X (fka Twitter)](https://twitter.com/intent/tweet?text=Hook into Netlify build events with Private Integrations&url=https://www.netlify.com/blog/hook-into-build-events-with-private-integrations/)
-   [LinkedIn](https://www.linkedin.com/shareArticle?mini=true&url=https%3A%2F%2Fwww.netlify.com%2Fblog%2Fhook-into-build-events-with-private-integrations%2F)
-   [Facebook](https://www.facebook.com/sharer.php?u=https://www.netlify.com/blog/hook-into-build-events-with-private-integrations/)
-   [Bluesky](https://bsky.app/intent/compose?text=Hook into Netlify build events with Private Integrations+https://www.netlify.com/blog/hook-into-build-events-with-private-integrations/)

* * *

### Tags

-   [Netlify SDK](/blog/tags/netlify-sdk/)
-   [Build Event Handlers](/blog/tags/build-event-handlers/)
-   [Integrations](/blog/tags/integrations/)
-   [changelog](/blog/tags/changelog/)

## Keep reading

![](/_astro/559af5ba0fe2cbe9e41bd2bc3bf83a5029232eed-2400x1260_ZsNdtr.webp)

News & Announcements October 20, 2023

[

### Announcing the General Availability of Private Integrations for Netlify Core

](/blog/general-availability-private-integrations-for-netlify-core)

-   ![Profile picture of Jennifer Arguello](/_astro/45c20ec3c9bda671514f2906c85857d66e98da3c-512x512_Z1LqK5o.webp)
    
    Jennifer Arguello
    
-   ![Profile picture of Cat Allen](/_astro/5f5b62f8be63dbef6d68ddbd392be73ce149202e-512x512_jerfz.webp)
    
    Cat Allen
    

![](/_astro/2ccd16fd0e91660cfe66aae8c1091d0445dc32b2-2400x1260_ZFAs8Q.webp)

News & Announcements September 13, 2023

[

### Announcing the General Availability of Netlify Software Development Kit (SDK)

](/blog/general-availability-netlify-sdk-software-development-kit)

-   ![Profile picture of Jennifer Arguello](/_astro/45c20ec3c9bda671514f2906c85857d66e98da3c-512x512_Z1LqK5o.webp)
    
    Jennifer Arguello
    
-   ![Profile picture of Shane Thomas](/_astro/e8988cd183964cbcc5eae2cf1805fee875e648f3-398x282_ZMaWUY.webp)
    
    Shane Thomas
    
-   ![Profile picture of Cat Allen](/_astro/5f5b62f8be63dbef6d68ddbd392be73ce149202e-512x512_jerfz.webp)
    
    Cat Allen
    

## Recent posts

News & Announcements June 25, 2026

[

### Netlify Functions, designed for Agent Experience

](/blog/netlify-functions-designed-for-agent-experience)

-   ![Profile picture of Eduardo Bouças](/_astro/52958f21e8450baf6d8e60302341a984e220c0cd-512x512_13VDlu.webp)
    
    Eduardo Bouças
    

News & Announcements June 24, 2026

[

### How we measure Netlify’s Agent Experience

](/blog/how-we-measure-netlify-agent-experience)

-   ![Profile picture of Sean Roberts](/_astro/bbf2243f8171dbddd80ab2103622106cef84d125-512x512_Z1d2LKE.webp)
    
    Sean Roberts
    

Guides & Tutorials May 15, 2026

[

### How to build a real-time AI chatbot in minutes with Netlify Agent Runners (no backend)

](/blog/how-to-build-a-real-time-ai-chatbot-in-minutes-with-netlify-agent-runners-no-backend)

-   ![Profile picture of Nahrin Jalal](/_astro/f0e7c8f227a03fe58340c99ef5439d5a896c0733-272x272_Z23kDpD.webp)
    
    Nahrin Jalal
    

![](/_astro/3f255b372fa958df35802666ee33b4609b2d71bd-1200x1586_1VtE2D.webp)

### How do the best dev and marketing teams work together?

[Access the report](https://www.netlify.com/reports/2024-leadership-trend-report/access/)