Feeds
The feeds namespace controls Ripllo's product-feed surface — today, the Google Merchant Center XML feed that Google Shopping and Performance Max ingest, with hooks for Meta Catalog and TikTok Shop in the same shape. Two endpoints: a merchant-scoped config CRUD, and a helper that builds the public XML feed URL Google polls. This page covers ripllo.feeds on the Node SDK. For the HTTP surface and the full XML shape, see API → Feeds.
Namespace
ripllo.feeds.getConfig()
ripllo.feeds.updateConfig(input)
ripllo.feeds.googleFeedUrl(accountId) // local helper, no network call
The config is deliberately small: a master toggle, a default Google product category, and whether to include unpublished products. That's the whole surface — there is no currency, brand-fallback, condition or product-exclusion setting. The XML is built on demand, per request, from the mirrored product table; nothing is cached or pre-generated. googleFeedUrl is purely a local string builder, not a method that touches the network.
Methods
feeds.getConfig
Signature. ripllo.feeds.getConfig(): Promise<MerchantFeedConfig>
Returns the calling workspace's feed config. Always returns a record: if the merchant has never saved one, you get the defaults (enabled: true, defaultGoogleProductCategory: null, includeUnpublished: false) rather than null.
const cfg = await ripllo.feeds.getConfig();
console.log(cfg.enabled, cfg.defaultGoogleProductCategory, cfg.includeUnpublished);
feeds.updateConfig
Signature. ripllo.feeds.updateConfig(input): Promise<MerchantFeedConfig>
PATCH semantics — pass only the fields you want to change. Upserts, so the first call creates the row.
await ripllo.feeds.updateConfig({
enabled: true,
defaultGoogleProductCategory: 'Apparel & Accessories > Clothing',
includeUnpublished: false,
});
The complete field list:
enabled— the master switch. Defaults totrue; the feed URL being unpublished is the real opt-in, since nothing polls it until you submit it to Merchant Center.defaultGoogleProductCategory— fallback taxonomy string used for any product without its owngoogleProductCategory. Nullable, max 200 chars.includeUnpublished— whenfalse(the default), only products marked available are emitted.marketingCampaignId— optional link to a marketing campaign. Must be a campaign in your own workspace or the PATCH is400 VALIDATION.
Unknown keys are dropped silently. The PATCH body is validated with a strict-ish schema and only recognised keys are copied into the update, so
updateConfig({ googleEnabled: true, currency: 'IDR' })returns200 OKhaving changed nothing — no error tells you the feed was never enabled. Useenabled, notgoogleEnabled.
feeds.googleFeedUrl
Signature. ripllo.feeds.googleFeedUrl(accountId: string): string
Returns the URL you give Google. Not an async call — it's a deterministic concat of the SDK's baseUrl plus the public feed path:
const url = ripllo.feeds.googleFeedUrl('acc_<merchant>');
// → 'https://ripllo.com/api/v1/feeds/google/acc_<merchant>.xml'
Drop this string into Google Merchant Center's "Add product feed → fetch URL" flow. The endpoint is public (no signing). An accountId with no mirrored products returns a well-formed but item-less <rss> document — but see the disabled-feed case under Errors, which is a 404 rather than empty XML.
Types
interface MerchantFeedConfig {
enabled: boolean;
defaultGoogleProductCategory: string | null;
includeUnpublished: boolean;
}
That is the SDK's declared shape. The row the API returns also carries id, accountId, marketingCampaignId, createdAt and updatedAt; the defaults stub returned for a merchant who has never saved a config carries only the three fields above.
Common patterns
Hand the URL off to Google Merchant Center
const cfg = await ripllo.feeds.getConfig();
if (!cfg.enabled) {
await ripllo.feeds.updateConfig({ enabled: true });
}
const feedUrl = ripllo.feeds.googleFeedUrl(merchantAccountId);
console.log(`Add this URL to Merchant Center:\n ${feedUrl}`);
Hide a product from Shopping
There is no exclusion list on the feed config. The feed emits every non-archived mirrored product, filtered only by availability: with includeUnpublished: false (the default) an unavailable product drops out of the feed. To hide something from Shopping, mark it unavailable on the storefront side — Ripllo has no per-product feed override.
Sniff the feed locally
const url = ripllo.feeds.googleFeedUrl(accountId);
const res = await fetch(url);
const xml = await res.text();
console.log(`${xml.match(/<item>/g)?.length ?? 0} items in feed`);
The feed surface is public, so this works without any signing.
Errors
| Code | Status | Cause |
|---|---|---|
VALIDATION |
400 | defaultGoogleProductCategory over 200 chars, wrong types, or a marketingCampaignId that isn't in your workspace. |
NO_ACCOUNT |
403 | The principal carries no accountId. |
INSUFFICIENT_SCOPE |
403 | API key lacks read (for GET /feeds/config) or write (for the PATCH). Scopes are enforced; ripllo:platform:admin is a superset of both. |
The public XML endpoint never returns the API error envelope, but it is not always XML either:
- Feed disabled (
enabled: falseon a saved config) →404withtext/plainbodyfeed disabled. This is what Merchant Center sees when a merchant switches the feed off — a fetch failure, not an empty catalogue. Check here first when Google reports it can't retrieve the feed. - Any other case →
200with anapplication/xml<rss>document, which may legitimately contain zero<item>elements (unknown account, no mirrored products, or everything filtered out byincludeUnpublished). The feed is capped at 5000 products, newest-updated first.
Next
- Pixels — companion analytics-tracking surface.
- API → Feeds — the full XML shape and crawl behaviour.