Show equivalents on a product page
Render the equivalents of an item on your own product page, in the order given, with safety flags, the disclaimer and a link to who stocks it.
This is a worked example, not a supported connector. Interchange does not build or run connectors. You own the code you write from it, and the support boundary applies. Read the support boundary.
This recipe needs no key.
How it works
Call from your server
Fetch the equivalents on your server and cache the page for no more than 12 hours. A key, if you use one, must never reach a browser.
Keep the order
Equivalents arrive sorted by brand, A to Z. Do not reorder them by margin, stock or anything else.
Keep near matches apart
Near matches are different items. List them separately with the stated difference, never among the equivalents.
Show the flags and the disclaimer
Show every safety flag in the words given, and
usage.disclaimer. Crediting Interchange withusage.attributionis a strong request, not a condition.Fail closed
On a 410 show nothing for that item. On any other error show no equivalents rather than an old guess.
The code
Node 22, no libraries. Adapt it to your language and your storage.
const BASE = "https://api.interchangeparts.com.au";
const escapeHtml = (s) =>
String(s).replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]);
// Run this on your server and cache the result for no more than 12 hours. Never call from a browser with a key.
export async function equivalentsHtml(ixId) {
const response = await fetch(BASE + "/v1/items/" + encodeURIComponent(ixId) + "/equivalents?include_near=true", {
headers: { Accept: "application/json" },
});
const answer = await response.json();
if (response.status === 410) return ""; // withdrawn: show nothing at all
if (response.status !== 200) return "<!-- equivalents unavailable -->"; // fail closed. Do not show a stale guess.
const flags = answer.safety_flags
.map((f) => '<p class="warning"><strong>' + escapeHtml(f.severity) + ":</strong> " + escapeHtml(f.message) + "</p>")
.join("");
// Show the order you were given. It is by brand, A to Z, and must not be re-ordered by anything else.
const rows = answer.status === "no_verified_match"
? "<p>Interchange has no verified equivalent for this part. That does not mean none exists.</p>"
: "<ul>" + answer.equivalents.map((e) =>
"<li>" + escapeHtml(e.brand) + " " + escapeHtml(e.part_number) + " (reviewed " + escapeHtml(e.reviewed) + ")</li>").join("") + "</ul>";
// Near matches fit the same way (or not) but are not the same part. Keep them apart, with the difference stated.
const near = (answer.near_matches ?? []).map((n) =>
"<li>" + escapeHtml(n.name) + ": " + n.differences.map((d) => escapeHtml(d.attribute + " is " + d.other_value + ", not " + d.this_value)).join(", ") + "</li>").join("");
return [
'<section aria-label="Equivalent parts">',
"<h2>Equivalents of " + escapeHtml(answer.name) + "</h2>",
flags, rows,
near ? "<h3>Near matches, not the same part</h3><ul>" + near + "</ul>" : "",
answer.meta.data_set === "sandbox" ? "<p>Sample data. Do not rely on it.</p>" : "",
"<p>" + escapeHtml(answer.usage.disclaimer) + "</p>",
'<p><a href="' + escapeHtml(answer.suppliers_url) + '">Who stocks it</a>. ' + escapeHtml(answer.usage.attribution) + "</p>",
"</section>",
].join("");
}
Watch for
- When
meta.data_setissandboxthe data is illustrative. Do not publish it to your customers. no_verified_matchmeans we do not know. Say that, and do not offer the nearest part.
The calls are described in the API reference.