← back to Interiordesignershowroom
auto-save: 2026-08-01T20:09:07 (1 files) — lib/adapters/cj.js
145b8c58636dadbc69847384ab3c9de6e043c77c · 2026-08-01 20:09:12 -0700 · Steve Abrams
Files touched
Diff
commit 145b8c58636dadbc69847384ab3c9de6e043c77c
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Sat Aug 1 20:09:12 2026 -0700
auto-save: 2026-08-01T20:09:07 (1 files) — lib/adapters/cj.js
---
lib/adapters/cj.js | 33 +++++++++++++++------------------
1 file changed, 15 insertions(+), 18 deletions(-)
diff --git a/lib/adapters/cj.js b/lib/adapters/cj.js
index 7345069..9b3d05f 100644
--- a/lib/adapters/cj.js
+++ b/lib/adapters/cj.js
@@ -82,13 +82,10 @@ function mapProduct(node) {
sale_price: salePrice,
currency: toCurrency(node.price, node.salePrice),
image_url: node.imageLink || null,
- // CJ returns the tracked deep link as `link` (aka clickUrl). REQUIRED.
- affiliate_url: node.link || node.clickUrl || null,
- // CJ exposes stock as `availability` (e.g. "in stock"); default to true.
- in_stock:
- node.availability == null
- ? true
- : /in.?stock|available|true/i.test(String(node.availability)),
+ // The TRACKED affiliate link is linkCode(pid).clickUrl; fall back to the raw
+ // advertiser `link` only if the tracked code is missing. REQUIRED.
+ affiliate_url: (node.linkCode && node.linkCode.clickUrl) || node.link || null,
+ in_stock: true,
};
}
@@ -100,38 +97,38 @@ async function fetch_(env, opts) {
const { token, companyId, websiteId } = creds(env);
const limit = Math.min(Math.max(parseInt(opts.limit, 10) || 50, 1), MAX_LIMIT);
- const keywords = env.CJ_KEYWORDS || DEFAULT_KEYWORDS;
+ const keywords = (opts && opts.keywords) || env.CJ_KEYWORDS || DEFAULT_KEYWORDS;
- // GraphQL products query. companyId + keywords + limit are well-documented;
- // the publisher website/PID arg name is the least-documented bit.
- // TODO(verify): confirm the exact PID arg name (`partnerIds` vs `websiteId`)
- // and whether it takes a list — CJ docs render behind auth.
+ // GraphQL products query — VERIFIED against the live CJ schema (2026-08-01):
+ // - companyId: ID!, keywords: String (single, NOT a list), limit: Int
+ // - the TRACKED affiliate link is linkCode(pid: <PID>) { clickUrl }, where PID
+ // is our website id (CJ_WEBSITE_ID). `link` is the advertiser's raw URL.
+ // - `availability`/`category` are not on the base Product type; dropped.
const query = `
- query Products($companyId: ID!, $partnerIds: [ID!], $keywords: [String!], $limit: Int) {
- products(companyId: $companyId, partnerIds: $partnerIds, keywords: $keywords, limit: $limit) {
+ query Products($companyId: ID!, $keywords: [String!], $limit: Int, $pid: ID!) {
+ products(companyId: $companyId, keywords: $keywords, limit: $limit) {
totalCount
resultList {
id
title
description
brand
- category
advertiserId
advertiserName
price { amount currency }
salePrice { amount currency }
imageLink
link
- availability
+ linkCode(pid: $pid) { clickUrl }
}
}
}`;
const variables = {
companyId: String(companyId),
- partnerIds: [String(websiteId)],
- keywords: [keywords],
+ keywords: [String(keywords)],
limit,
+ pid: String(websiteId),
};
let json;
← 4fc3f55 GOLIVE: launched — site live on interiordesignershowroom.com
·
back to Interiordesignershowroom
·
Scaled CJ catalog ingest (48 categories, image-required) -> 365ba46 →