// ==UserScript== // @namespace https://openuserjs.org/users/Taddiboy // @name Amazon - Show seller info // @name:de Amazon - Verkäuferinformationen anzeigen // @name:fr Amazon - Afficher les informations sur le vendeur // @name:es Amazon - Mostrar información del vendedor // @name:it Amazon - Mostra info venditore // @description Shows country of origin and ratings for third party sellers on Amazon (and highlights Chinese sellers) // @description:de Zeigt Herkunftsland und Bewertungen von Drittanbietern auf Amazon (und hebt chinesische Anbieter hervor) // @description:fr Montre le pays d'origine et les notations des vendeurs tiers sur Amazon (et met en évidence les vendeurs chinois) // @description:es Muestra el país de origen y las calificaciones de los vendedores terceros en el Amazon (y destaca los vendedores chinos) // @description:it Mostra il paese di origine e le valutazioni per i venditori di terze parti su Amazon (e mette in evidenza i venditori cinesi) // @copyright 2020, Taddiboy (https://openuserjs.org/users/Taddiboy) // @license MIT // @author Taddiboy // @version 1.0.0 // @icon https://i.imgur.com/u4v223v.png // @include /^https:\/\/(www|smile)\.amazon\.(co\.uk|de|es|fr|it)\/.*$/ // @grant GM_addStyle // @grant GM_xmlhttpRequest // @downloadURL none // ==/UserScript== (function() { 'use strict'; // CONFIG BEGIN const highlightedCountries = ['CN', 'HK']; // Country codes as per ISO 3166 ALPHA-2 // Set to [] to highlight no sellers at all // Set to ['FR'] to highlight sellers from France // Supported country codes: https://www.countryflags.io/#countries // Default: ['CN', 'HK'] const redirectToSmile = false; // Available for amazon.de and amazon.co.uk // Set to true to redirect to Amazon Smile // Set to false for no redirect // Default: false const showConsoleLog = false; // Show errors in console log // Default: false // CONFIG END if (redirectToSmile && top.location.href.match(/^https:\/\/smile\.amazon\.(de|co\.uk)\//i) === null) { window.location.replace(window.location.href.replace(/^https:\/\/www\./i, "https://smile.")); } // Check URLs for page type (search result page and best sellers page) const isSearchResultPage = window.location.href.match(/.*\.amazon\..*\/s\?.*/); const isBestsellersPage = window.location.href.match(/.*\.amazon\..*\/gp\/bestsellers\/.*/) || window.location.href.match(/.*\.amazon\..*\/Best\-Sellers\-.*/); if (isSearchResultPage || isBestsellersPage) { function showSellerCountry() { 'use strict'; const products = isSearchResultPage ? document.querySelectorAll('h2.a-size-mini.a-spacing-none.a-color-base a.a-link-normal.a-text-normal:not([data-seller])') : document.querySelectorAll('span.aok-inline-block.zg-item>a.a-link-normal:not([data-seller])'); for (let i = 0; i < products.length; i++) { const product = products[i]; product.setAttribute("data-seller", "set"); if (product.href && product.href.match(/.*\.amazon\..*\/(.*\/dp|gp\/slredirect)\/.*/)) { GM_xmlhttpRequest({ method: "GET", url: product.href, responseType: "document", onload: function(responseProduct) { const productPage = parse(responseProduct); const thirdPartySeller = productPage.querySelector('#qualifiedBuybox #sellerProfileTriggerId, #newAccordionRow #sellerProfileTriggerId, #shipsFromSoldBy_feature_div #sellerProfileTriggerId'); const isThirdPartySeller = thirdPartySeller !== null; if (isThirdPartySeller) { thirdPartySeller.textContent = thirdPartySeller.textContent.trim(); thirdPartySeller.href = thirdPartySeller.href.replace(/gp\/help\/seller.*/g, 'sp?' + thirdPartySeller.href.match(/(seller=.*?)(&|$)/)[1]); const sellerInfoLink = document.createElement("a"); sellerInfoLink.href = thirdPartySeller.href; const sellerInfoContent = document.createTextNode(thirdPartySeller.textContent); sellerInfoLink.appendChild(sellerInfoContent); sellerInfoLink.classList.add("seller-info"); isSearchResultPage ? product.parentNode.parentNode.appendChild(sellerInfoLink) : product.parentNode.insertBefore(sellerInfoLink, product.parentNode.querySelector('.a-icon-row.a-spacing-none')); GM_xmlhttpRequest({ method: "GET", url: thirdPartySeller.href, responseType: "document", onload: function(responseSeller) { const sellerPage = parse(responseSeller); // Get seller rating let rating = sellerPage.getElementById('seller-feedback-summary'); if (rating !== null) { let ratingPercentage = ''; let ratingCount = ''; if (sellerPage.getElementById('feedback-no-rating')) { ratingPercentage = sellerPage.getElementById("feedback-no-rating").textContent; } else { ratingPercentage = sellerPage.getElementsByClassName('feedback-detail-description')[0].textContent.match(/\d+%/); } if (rating.contains(sellerPage.getElementById('feedback-no-review'))) { ratingCount = sellerPage.getElementById("feedback-no-review").textContent; } else { ratingCount = sellerPage.getElementsByClassName('feedback-detail-description')[0].textContent.match(/\(([^)]+)\)/)[1]; } const sellerInfoRatingText = ' (' + ratingPercentage + ' | ' + ratingCount + ')'; const sellerInfoRating = document.createTextNode(sellerInfoRatingText); sellerInfoLink.appendChild(sellerInfoRating); } else { if (showConsoleLog) { console.log("Too many requests. Cannot open seller pages anymore :-\(") } } // Get seller country & flag const sellerUl = sellerPage.querySelectorAll("ul.a-unordered-list.a-nostyle.a-vertical"); //get all ul if (sellerUl !== 'undefined' || 0 !== sellerUl.length) { const sellerUlLast = sellerUl[sellerUl.length - 1]; //get last list const sellerLi = sellerUlLast.querySelectorAll("li"); //get all li const sellerLiLast = sellerLi[sellerLi.length - 1]; //get last li const sellerCountry = sellerLiLast.textContent; if (sellerCountry.length == 2) { var flag = document.createElement("img"); flag.setAttribute("src", "https://www.countryflags.io/" + sellerCountry.toLowerCase() + "/flat/32.png"); flag.setAttribute("width", "16"); flag.setAttribute("height", "16"); flag.setAttribute("style", "margin-right: 5px;"); flag.title = sellerCountry; sellerInfoLink.prepend(flag); // Highlight sellers from countries defined in 'highlightedCountries' if (highlightedCountries.includes(sellerCountry)) { const outercontainer = isSearchResultPage ? product.closest('.a-carousel-card, .s-result-item') : product.closest('.zg-item-immersion'); const productImage = isSearchResultPage ? outercontainer.querySelector('.s-image') : outercontainer.querySelector('.zg-text-center-align img'); outercontainer.style.background = "linear-gradient(180deg, rgba(222,41,14,0.33) 0%, rgba(222,41,14,0) 100%)"; productImage.style.opacity = "0.66"; } } else { if (showConsoleLog) { console.log("Seller \"" + thirdPartySeller.textContent + "\" has no valid imprint.") } } } else { if (showConsoleLog) { console.log("Something went wrong while getting seller info of \"" + thirdPartySeller.textContent + "\".") } } } }); } else { const sellerInfoDiv = document.createElement("div"); let soldbyAmazon = productPage.querySelector('#merchant-info').textContent.trim(); if (!soldbyAmazon.replace(/\s/g, '').length) { soldbyAmazon = '? ? ?'; } else { const svg = document.createElement("span"); svg.innerHTML = ''; sellerInfoDiv.appendChild(svg); } const sellerInfoContent = document.createTextNode(soldbyAmazon); sellerInfoDiv.appendChild(sellerInfoContent); sellerInfoDiv.classList.add("seller-info"); isSearchResultPage ? product.parentNode.parentNode.appendChild(sellerInfoDiv) : product.parentNode.insertBefore(sellerInfoDiv, product.parentNode.querySelector('.a-icon-row.a-spacing-none')); } } }); } } } // Run script once on document ready showSellerCountry(); // Initialize new MutationObserver const mutationObserver = new MutationObserver(showSellerCountry); // Let MutationObserver target the grid containing all thumbnails const targetNode = document.body; const mutationObserverOptions = { childList: true, subtree: true } // Run MutationObserver mutationObserver.observe(targetNode, mutationObserverOptions); function parse(targetPage) { const parser = new DOMParser(); return parser.parseFromString(targetPage.responseText, "text/html"); } // Add Google's own CSS used for image dimensions GM_addStyle(` .seller-info { display: inline-block; background: #fff; color: #1d1d1d !important; font-size: 11px; line-height: 15px; padding: 2px 5px; font-weight: 400; border: 1px solid #E0E0E0; margin-top: 4px; height: 22px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; } a.seller-info:hover { border-color: #D0D0D0; text-decoration: none; background-color: #F3F3F3; } #zg-center-div .zg-item-immersion { height: 390px; } `); } })();