Skip to content

Marketplace Channels

Sell a shop's products on marketplaces and shopping channels (eBay and Google Shopping today) without keeping a second catalogue. Badger stays the system of record: products, stock and orders live here, the channel reads from them, and marketplace orders come back into Badger as ordinary orders that are packed and dispatched with everything else.

Channel Listings Orders Dispatch, cancel, refund Payouts
Google Shopping (Merchant Center free listings) Yes No (shoppers buy on your site) n/a n/a
eBay Yes, including variations Imported automatically Sent back to eBay Fetched and reconciled

Channels are off by default. Turn on Marketplace channels (channels-enabled, under Settings > Integrations) to show Channels in the admin menu.

Status

The eBay and Google connectors are written against the marketplaces' published APIs but have not yet been run against a live eBay or Merchant Center account. Treat the first connection on each platform as a pilot.

How it works

  1. Connect an account. eBay: choose the marketplace (eBay UK, US, ...) and sign in to eBay to grant access. Google: add Badger's service account email as a user of your Merchant Center, then enter your Merchant Center id. One site can connect several accounts.
  2. Choose your settings. Price rule (e.g. +10% to cover fees), how much stock to hold back for your own site, the most units to offer, handling days, whether to import orders, whether to publish automatically, and for eBay your business policies (postage, payment, returns) and where items ship from.
  3. Map your categories. For each taxonomy level (or collection), pick the channel category its products go in, and say how your attributes fill the channel's (e.g. your "Material" → eBay "Fabric", "Navy" → "Blue"). A single product can also have its own category.
  4. Add products. Pick them one by one, or add everything on a category page of your category tree, a taxonomy category (sub-categories included) or a collection. Badger checks each product against the channel: missing images, prices, required attributes (eBay item specifics), barcodes where the category needs them, and products that can't be sold there. Each listing shows what's stopping it in plain words.
  5. Fill the gaps with AI. For a listing that's missing attributes, Suggest with AI proposes values from the product's own title, description and attributes. Nothing is published until you accept them.
  6. Publish. Ready listings go out when you press Publish (or straight away with automatic publishing). After that, changes to the product are republished automatically, and stock levels are pushed every 15 minutes.
  7. Orders arrive. Paid eBay orders are imported every couple of minutes as marketplace orders: stock is taken, the order gets a number and appears in the fulfilment queue. eBay sends the buyer its own emails, so Badger doesn't.
  8. Dispatch as usual. Dispatching with a carrier and tracking number sends them to eBay. Cancelling sends a cancellation; a refund is made on eBay.
  9. Reconcile payouts. Each eBay payout is fetched with its sales, refunds and fees, matched to Badger orders, and marked reconciled when it adds up.

What can't be listed

Donations, gift cards, event tickets and subscriptions are not eligible. eBay only takes items that are posted. Disabled variants aren't offered.

Marketplace orders

A marketplace order is an Order with channel = MARKETPLACE and a channelRef naming the account and the marketplace's order id (unique per account, so an order is only ever imported once). Its payment is a MarketplacePaymentMethod intent, already captured: the buyer paid the marketplace, which pays the seller later in a payout.

  • Buyer details are kept on the order only (name, delivery address, the email the marketplace gives). Each account has one anonymous user that owns its imported orders, so buyers aren't created as customers.
  • Tax the marketplace collects (US marketplace-facilitator sales tax) is left out of the order's total and tax and recorded in channelRef.marketplaceTaxCollected, since the seller never receives it.
  • Orders that can't be imported (usually an eBay SKU that isn't on the site) are held back and listed on the account, and retried on every sync until they import. Fix the SKU on the eBay listing or the product.
  • Cancelled on eBay after import: the order is cancelled in Badger too (stock restored), without sending anything back to eBay.

The order pipelines:

Pipeline What happens for a marketplace order
importChannelOrder (new) Set submitted, take stock, number the order, auto-fulfil digital lines, record the sale, announce fulfilment work. No payment, no confirmation email.
dispatchOrder queueChannelShipmentProcessor queues the carrier and tracking for the marketplace. The dispatch email is skipped.
cancelOrder queueChannelCancellationProcessor queues a cancellation (unless the cancellation came from the marketplace). The refund the cancellation makes is recorded but not sent separately. The cancellation email is skipped.
refundOrder The marketplace payment method queues a refund for the marketplace.

Updates to the marketplace go through an outbox (ChannelTask): they're written when the order changes and sent by the worker with retries (backing off up to 6 hours, 12 attempts). Ones that keep failing are listed on the account with a Retry button, so a slow marketplace never holds up dispatch in Badger.

Architecture

Where What
common channels package Documents: ChannelAccount, ChannelListing, ChannelCategoryMapping, ChannelCategorySchema (cached, shared across sites), ChannelTask, ChannelPayout, and their repositories
commerce-core channels package Services: accounts (credentials encrypted with a per-site key, ChannelTokenCipher), listings and readiness (ChannelListingPreparer), mappings, order import, outbox, payouts, AI suggestions. Marketplace-neutral: no eBay or Google code
channels module ChannelConnector SPI, the eBay and Google connectors, ChannelOperations (connect, categories, policies for admin and MCP) and the sync job
worker Runs the sync job (badger.channels.sync.enabled: true)
web-admin The Channels screens and the eBay OAuth callback
ai MCP tools and the AI attribute suggester

The sync job leases one account at a time (claimNextDue, a findAndModify on the account), so several worker pods share accounts without syncing one twice. It runs every 30 seconds (badger.channels.sync.interval-ms) on its own thread, not the worker's shared @Scheduled pool, so a long job there (a big stock reindex) can't delay order imports. Each pass sends outbox updates, imports orders, publishes changed listings (25 per pass), pushes stock every 15 minutes, reads Google's review of live listings every 6 hours (and an hour after a publish) and fetches payouts every 6 hours. A refused credential stops the account (Needs reconnecting) until the owner reconnects; other failures back off.

Listings are flagged for republishing when their product is saved (from ProductIndexEvent), when a mapping or the account's settings change, or by the owner. A hash of the published payload stops unchanged products being re-sent; quantities don't count towards it.

From an AI agent (MCP)

The channels and manageChannels MCP tools do everything the Channels screens do: create and configure accounts, map categories, add products, ask for AI attribute suggestions and accept them, publish, and read payouts and failed updates. opsInbox counts accounts to reconnect, failed updates, orders that couldn't import, listings in error and live listings Google has since disapproved. An agent can't grant eBay access itself: it gets a link for the owner to open. See MCP.

Platform setup (superadmin)

Global settings, group channels-config:

Key What
channels-ebay-client-id, channels-ebay-client-secret The eBay developer keyset (sandbox or production)
channels-ebay-ru-name The RuName whose accepted URL is https://<platform host>/channels/oauth/ebay
channels-ebay-sandbox Use eBay's sandbox for every site (default on)
channels-google-service-account JSON key of a Google Cloud service account with the Merchant API enabled

Connecting checks that eBay can pay the seller (opted in to eBay managed payments for the marketplace, Account API payments_program). A seller eBay can't pay can list, but buyers can't check out, so the account doesn't connect until payments are set up in Seller Hub, and it says which steps are left. Check connection on the account runs the checks again without going back to eBay.

On the sandbox, an account's Settings page also offers Create test policies: a sandbox test seller has no business policies, so it makes a free Royal Mail postage, an eBay-managed payment and a 30-day returns policy (named "Badger sandbox test", reused if they exist) and chooses them. It's never offered against production eBay, where the seller sets their own postage and returns.

For Google, the Merchant API must be enabled on the service account's Google Cloud project, and that project registered once with developerRegistration.registerGcp against a Merchant Center where you're an admin. Shops then add the service account email as a user of their own Merchant Center (Settings > People and access) and enter their Merchant Center id; Badger creates a "Badger" API data source in it for the feed label (the account's country) and the site's language. Google reviews products after accepting them, sometimes days later. Its disapprovals and warnings are read back for the whole account every 6 hours, and an hour after a publish (products.list, a thousand products a call, so 20,000 products cost 20 calls), and replace the listing's previous review issues without a republish. Accounts with nothing live make no call, and sites without a channel account cost nothing: the worker only looks at accounts that are due.

Each Google product also carries the shop's own category paths as product types (its category in the main category tree, then its taxonomy level, e.g. "Fixings > Screws > Torx screws"), which Google uses for bidding and reports, and its taxonomy attributes as product details (a variant's own options first, such as its length). Attributes Google has a field for (colour, size, material, pattern, gender, age group, brand) go in that field instead, and one that differs between a product's variants is left off the product details.

The OAuth callback lands on the platform host, not the shop's domain. It carries a single-use state (random, hashed at rest, valid 15 minutes) that names the account, then redirects to that account's site admin.

Site data

Channel accounts, listings, mappings, outbox tasks and payouts are deleted with the site. They aren't included in site export: credentials are bound to the source site, and a copy would publish to the same marketplace account. The per-site credential key (channel-token-encryption-key) is a secret and is never exported.

Not built yet

  • Amazon (SP-API), Etsy, and other marketplaces.
  • Returns raised on the marketplace (handle them on eBay; refunds made there aren't imported yet).
  • Repricing rules beyond a single percentage per account, and multi-currency listings.
  • A REST contract for third-party connectors.