Skip to content

Instantly share code, notes, and snippets.

@dantetemplar
Last active November 19, 2025 19:21
Show Gist options
  • Select an option

  • Save dantetemplar/efcd3bd9e23f4073471f225931020c22 to your computer and use it in GitHub Desktop.

Select an option

Save dantetemplar/efcd3bd9e23f4073471f225931020c22 to your computer and use it in GitHub Desktop.
Sort Aliexpress items by total price: price + shipping
void (async () => {
// ---------- helpers ----------
const parseNumber = (text) => {
if (!text) return NaN;
text = text.replace(/\u00a0/g, " ");
const m = text.match(/(\d+[.,\s]?\d*)/);
if (!m) return NaN;
return Number(m[1].replace(",", ".").replace(" ", ""));
};
const parsePriceNearCurrency = (text) => {
if (!text) return NaN;
text = text.replace(/\u00a0/g, " ");
// число непосредственно рядом с символом валюты
const re = /(\d+[.,\s]?\d*)\s*(?:₽|€|\$|£|¥)|(?:₽|€|\$|£|¥)\s*(\d+[.,\s]?\d*)/g;
let match;
let last = null;
while ((match = re.exec(text)) !== null) {
last = match[1] || match[2];
}
if (last) return Number(last.replace(",", ".").replace(" ", ""));
// fallback: берём последнюю цифру в строке
const all = [...text.matchAll(/(\d+[., ]?\d*)/g)];
if (!all.length) return NaN;
return Number(all[all.length - 1][1].replace(",", "."));
};
const detectCurrencySymbol = (text) => {
if (!text) return "";
const symbols = ["₽", "€", "$", "£", "¥"];
for (const s of symbols) {
if (text.includes(s)) return s;
}
const match = text.match(/(AU\$|US\$|CA\$)/);
return match ? match[1] : "";
};
const getProductPriceLine = (card) => {
return card.querySelector(
".red-snippet_RedSnippet__price__q0mlsu, .red-snippet_RedSnippet__priceNew__q0mlsu"
);
};
const extractFromNewSnippetCard = (card) => {
const priceSpan = card.querySelector(
".red-snippet_RedSnippet__priceNew__q0mlsu span"
);
if (!priceSpan || !priceSpan.textContent) return null;
const priceText = priceSpan.textContent;
const productPrice = parseNumber(priceText);
if (!Number.isFinite(productPrice)) return null;
const currencySymbol = detectCurrencySymbol(priceText) || "";
const shippingSpan =
card.querySelector(
".red-snippet_RedSnippet__delivery__q0mlsu span[title]"
) ||
card.querySelector(
".red-snippet_RedSnippet__delivery__q0mlsu span"
);
let shippingCost = 0;
if (shippingSpan && shippingSpan.textContent) {
const shippingText = shippingSpan.textContent.toLowerCase();
if (shippingText.includes("бесплатн") || shippingText.includes("free")) {
shippingCost = 0;
} else {
const parsed = parsePriceNearCurrency(shippingSpan.textContent);
if (Number.isFinite(parsed)) shippingCost = parsed;
}
}
return { productPrice, shippingCost, currencySymbol };
};
// ---------- main logic ----------
const productCards = document.querySelectorAll(
".red-snippet_RedSnippet__container__q0mlsu"
);
if (!productCards.length) {
console.error("No product cards found. Layout may have changed again.");
return;
}
for (const card of productCards) {
const info = extractFromNewSnippetCard(card);
if (!info) {
console.error("Could not parse price/shipping for card:", card);
continue;
}
const { productPrice, shippingCost, currencySymbol } = info;
const shippedPrice = productPrice + shippingCost;
card.dataset.shippedPrice = String(shippedPrice);
const priceLine = getProductPriceLine(card);
if (!priceLine) {
console.error("Price line not found for card:", card);
continue;
}
const currencyStr = currencySymbol ? " " + currencySymbol : "";
const shippedHtml = `
<div style="font-size: 12px; margin-top: 4px;">
Shipped: <b>${shippedPrice.toFixed(2)}${currencyStr}</b>
<span style="opacity: 0.7;">
(${productPrice.toFixed(2)} + ${shippingCost.toFixed(2)})
</span>
</div>
`;
priceLine.insertAdjacentHTML("beforeend", shippedHtml);
}
const container =
document.querySelector(".SnowSearchProductFeed_List__grid__wbj7b") ||
document.querySelector(".red-snippet_RedSnippet__grid__q0mlsu") ||
document.querySelector("#card-list");
if (!container) {
console.error("Container not found, can't sort");
return;
}
const sortedCards = Array.from(container.children).sort((a, b) => {
const pa = Number(a.dataset.shippedPrice ?? "Infinity");
const pb = Number(b.dataset.shippedPrice ?? "Infinity");
return pa - pb;
});
container.innerHTML = "";
for (const card of sortedCards) {
container.appendChild(card);
}
console.log("Done: cards annotated with shipped price and sorted.");
})();
@dantetemplar
Copy link
Author

dantetemplar commented Nov 19, 2025

Note that will work only for aliexpress.ru, for aliexpress.com use aliexpress-show-shipped-price. Just open some search in aliexpress, Press F12 and paste the code. May be you need to type "allow pasting" if this is your first time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment