Appearance
How to add extra data to a feed ​
Extra data lets you enrich your products with supplementary information that isn't present in your source catalog. You import an additional data set, match it to your products, and the extra fields become available throughout Feedr - ready to map into your feed output, use in filters, or reference in templates.
This is useful when the data you need lives outside your main product source - for example margins or cost prices from a finance export, stock levels from a warehouse system, or custom labels and metadata maintained in a separate spreadsheet.
Google Sheets Apps Script Code ​
Use and adapt this code in "Apps Script"
js
// ========= CONFIG: edit this block per feed =========
var CONFIG = {
feedUrl: 'https://example.com/your-feed.xml', // the feed URL
sheetName: 'Feed', // tab to write into (created if missing)
itemElement: 'item', // "item" for RSS feeds, "entry" for Atom feeds
fields: [
// tag names you want, in column order
'id',
'item_group_id',
'title',
'custom_label_1',
'custom_label_2',
'custom_label_3',
'custom_label_4',
],
};
// ====================================================
function importFeed() {
// Fetch
var response = UrlFetchApp.fetch(CONFIG.feedUrl, {
muteHttpExceptions: true,
});
if (response.getResponseCode() !== 200) {
throw new Error('Fetch failed with status ' + response.getResponseCode());
}
// Parse and find all item/entry elements anywhere in the tree
var doc = XmlService.parse(response.getContentText());
var items = [];
collectElements(doc.getRootElement(), CONFIG.itemElement, items);
if (items.length === 0) {
throw new Error(
'No <' +
CONFIG.itemElement +
'> elements found. Check the "itemElement" setting.',
);
}
// Build rows: header + data
var rows = [CONFIG.fields.slice()]; // header row = field names
for (var i = 0; i < items.length; i++) {
var row = [];
for (var f = 0; f < CONFIG.fields.length; f++) {
row.push(getFieldValue(items[i], CONFIG.fields[f]));
}
rows.push(row);
}
// Write in one batch
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet =
ss.getSheetByName(CONFIG.sheetName) || ss.insertSheet(CONFIG.sheetName);
sheet.clearContents();
sheet.getRange(1, 1, rows.length, rows[0].length).setValues(rows);
ss.toast(items.length + " items imported into '" + CONFIG.sheetName + "'.");
}
// Returns the text of the first child whose tag name matches, ignoring namespace.
function getFieldValue(item, fieldName) {
var children = item.getChildren();
for (var i = 0; i < children.length; i++) {
if (children[i].getName() === fieldName) {
return children[i].getText();
}
}
return ''; // field missing on this item
}
// Recursively collects all elements with the given tag name (namespace ignored).
function collectElements(element, name, result) {
var children = element.getChildren();
for (var i = 0; i < children.length; i++) {
var child = children[i];
if (child.getName() === name) {
result.push(child);
} else {
collectElements(child, name, result);
}
}
}