How to build a Custom Editor plugin for my ecommerce backend with Builder.io

Integrating your e-commerce backend with Builder.io makes working with your product content and data so much easier, and unlocks use cases like:

  • Symbols or Custom components that can accept a resource identifier, giving the content creator a way to search and choose a specific resource. One example could be a custom component that takes a product collection as an input and renders all its products in a grid.

  • Targeting content by a resource, for example, an announcement bar where its content only targets visitors who have a specific product in their cart, or are identified by a specific persona.

The most straightforward way to integrate your backend is using a @builder.io/commerce-plugin-tools, and here are some steps to build your own custom backend plugin:

  1. clone Builder repository and then navigate to the plugin example folder here:
git clone https://github.com/BuilderIO/builder.git
# start from a preconfigured plugin code by copying its content to another folder
cp -r plugins/swell plugins/[my-backend]
npm install @builder.io/commerce-plugin-tools
  1. Delete content of src/plugin.tsx, so we replace it with the new backend operation, then start by
import { registerCommercePlugin } from '@builder.io/commerce-plugin-tools';

const pluginConfig = {
  // id should match the name in package.json
  id: `@foobar/plugin-builder`,
  // will be used to prefix generated types
  name: 'FooBar',
  // a list of input definition that you might need to communicate with custom backend API ( optional )
  settings: [
    {
      type: 'text',
      name: 'storeApiKey',
      helperText: 'you can get your store Api Key from your account at https://foobar.io/account',
    }
  ],
  ctaText: 'Connect your FooBar backend',
};

registerCommercePlugin(pluginConfig, (settings) => {
  const storeApiKey = settings.get('storeApiKey');
  const fooBarService = new FooBarService(storeApiKey);
  // return a mapping between each resource and it's API functions.
  return {
    // for example to add product types
    product: {
      findById: id => fooBarService.findProductById(id),
      search: text => fooBarService.searchProducts(text),
     // should return BuilderRequest interface
     // https://github.com/BuilderIO/builder/blob/master/plugins/shopify/src/interfaces/builder-request.ts
      getRequestObject: id => ({
        '@type': '@builder.io/core:Request',
        request: {
          // tell builder how to load this object
          url: `https://foobarservice.com/products/${id}.json`,
        },
        options: {
          product: id,
        },
      })
     }
  }
})

Now that we connected our API, we can check to see if it’s working correctly by running locally

npm install
npm run start

Start a server at http://localhost:1268

Go to the Builder plugin settings and add your local plugin https://localhost:1268/plugin.system.js?pluginId=@foobar/plugin-builder`

Now you should see new field types for products, such as:

  • A single product picker with search
  • A product list picker with search
  • A custom field: product preview, that allows you to set the specific model editing url to be a computed value of the product in preview: for example ${space.siteUrl}/product/${previewProduct.handle} and allow the content editor to test their templates on multiple products.

se

Once you’re done testing your new integration, submit a pull request to Builder with the new code, we’ll help review it, and publish it to npm. Or, if you’d like it to be a private plugin, talk to us, and we can support private plugins as part of an enterprise plan.

See more:

Swell.is plugin source code for a more concrete example.

Extensibility docs for more ways on how Builder can be extended.

HI,

I’m trying to get this working for our custom backend, but the components aren’t showing up in then editor.

I’ve edited the swell plugin to use our way of getting data, renamed everything that’s needed and added it as a plugin as described. When I open the editor, the mentioned components do not show up. I’ve enabled the Shopify components (as those are used in the demo GIF) for my space, but those always do a request to the Shopify API.
The custom fields do show up on the type selector for custom fields.

Where do I go from here? I can’t find a tutorial or documentation page that explains what to do after you connect your plugin to your space.

Hope someone can guide me to trough the next steps.

Hello @gijsbotje thanks for the question! When you say “components” you are trying to pull some sort of custom component from your backend into Builder through the plugin you wrote? Unfortunately that may not be supported with our current plugin tools.

Builder’s e-commerce plugins create custom field types corresponding to your external platform’s resources, which you can use when targeting content, previewing content, and using your content as a symbol inside of our Visual Editor.. They don’t necessarily allow you to register custom components.

We are actually in the middle of overhauling our plugin/integrations documentation, and I will be sure to link it here when it is done (hopefully sometime next week). Hopefully this, and our soon to be updated docs will help further clarify any confusion !

Hi @TimG thanks for the reply. In the OP it says Now you should see multiple content blocks for products. It also contains a GIF that displays how to add a collection block. I assumed it would show up like the Shopify blocks but nothing came up and using the Shopify blocks didn’t work either.
I’ve scoured almost all ecommerce plugins and the Shopify starter too and found what I needed to know. I also noticed that the GIF in the OP is being reused in every ecommerce plugins readme, which also led me to believe the plugins triggered those components.

Anyway, the Swell plugin is a good starting point, eventually I got there and can now select the products in the editor. Also found the components I needed to copy code from.

Looking forward to the updated documentation!

1 Like

Thanks so much for pointing that out, updated the wording to match the docs ( field types )

1 Like

This is officially linked from the documentation here but it is very old and I believe, quite out of date.

I followed the steps above and was first greeted by an inability to run npm install without --force. There appear to be a number of dependency issues. I am on Node.js 18 so if that’s incorrect, please instruct.

Then after using --force on pretty much every npm command, I tried the npm run start command and I get the following:

Error loading `tslib` helper library.
[!] Error: Package subpath './package.json' is not defined by "exports" in /home/davidrhoderick/Development/martingale/vrio-pages/builder.io-plugin-basic/node_modules/rollup-plugin-typescript2/node_modules/tslib/package.json
Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './package.json' is not defined by "exports" in /home/davidrhoderick/Development/martingale/vrio-pages/builder.io-plugin-basic/node_modules/rollup-plugin-typescript2/node_modules/tslib/package.json
    at new NodeError (node:internal/errors:400:5)
    at exportsNotFound (node:internal/modules/esm/resolve:361:10)
    at packageExportsResolve (node:internal/modules/esm/resolve:697:9)
    at resolveExports (node:internal/modules/cjs/loader:538:36)
    at Function.Module._findPath (node:internal/modules/cjs/loader:607:31)
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:1025:27)
    at Function.Module._load (node:internal/modules/cjs/loader:885:27)
    at Module.require (node:internal/modules/cjs/loader:1105:19)
    at require (node:internal/modules/cjs/helpers:103:18)
    at Object.<anonymous> (/home/davidrhoderick/Development/martingale/vrio-pages/builder.io-plugin-basic/node_modules/rollup-plugin-typescript2/src/tslib.ts:11:23)

It seems as though it’s not possible to follow these directions. Are there more up-to-date ones?

Thanks for flagging this, I’ll revisit asap, for now I think the easiest path is to clone an ecommerce plugin from the open source, most recent one is this plugin: builder/plugins/salesforce-commerce-api-plugin at main · BuilderIO/builder · GitHub

I’d copy it and modify it to fit your ecom API.

1 Like

Hey Dave! Thanks again for your feedback and glad to talk to you again.
We’ve pushed updates to our swell plugin (builder/plugins/swell at main · BuilderIO/builder · GitHub), so I believe you won’t be facing any issues with this newer version, I hope you find this a good point to start building your own.

Thanks for reaching out and let us know if you have any more feedbacks!

Thanks @aziz! Using the Salesforce plugin gave me better results. @gustavohgs I tried the Swell one earlier today and still had issues. Perhaps updating the documentation to point to the Salesforce one is the way to go?

The issue I’m having is that our API is not public. We can access it using an API key but you need to make the request from a server, you cannot do so easily from the browser. Do we have to have a browser-accessible API for data access?

For example, I’m able to get the data using getAsyncProps in getServerSideProps in my Next.js application (and presumably would have the same results with getStaticProps). However, I cannot preview that data from Builder because we need a server to do it. Is there any way to run the requests on a server? Or perhaps using a webhook to do trigger it?

Hey @vrio_dave, sorry you are still facing some issues, maybe we should go on a technical session so we can sort your issues out. Either way, some of our plugins uses our own proxy to fetch data on their own, if you take a look at the big commerce plugin as an example (builder/plugin.ts at main · BuilderIO/builder · GitHub) you will see the snippet const baseUrl = (url: string) => { const endUrl = https://api.bigcommerce.com/stores/${storeHash}/v3/catalog/${url}`;
return https://cdn.builder.io/api/v1/proxy-api?url=${encodeURIComponent(endUrl)};
};`

Feel free to use our proxy to make thins work on your end for your plugin, but maybe in the near future or on a technical session we can discuss on a custom alternative for you.

Hi, I was following this but got following error.
It appreciated if anyone guild me to right direction.

âžś  builder git:(main) âś— ni @builder.io/commerce-plugin-tools
npm ERR! code EUNSUPPORTEDPROTOCOL
npm ERR! Unsupported URL Type "workspace:": workspace:*

npm ERR! A complete log of this run can be found in: /Users/shinta/.npm/_logs/2024-01-03T06_06_32_816Z-debug-0.log