// ==UserScript== // @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 // @namespace https://github.com/TadWohlrapp/UserScripts // @description Shows name, country of origin and ratings for third party sellers on Amazon (and highlights Chinese sellers) // @description:de Zeigt Name, Herkunftsland und Bewertungen von Drittanbietern auf Amazon (und hebt chinesische Anbieter hervor) // @description:fr Montre le nom, le pays d'origine et les évaluations des vendeurs tiers sur Amazon (et met en évidence les vendeurs chinois) // @description:es Muestra el nombre, el país de origen y las valoraciones de los vendedores de terceros en el Amazon (y destaca los vendedores chinos) // @description:it Mostra il nome, il paese di origine e le valutazioni per i venditori di terze parti su Amazon (e mette in evidenza i venditori cinesi) // @icon https://github.com/TadWohlrapp/UserScripts/raw/master/amazon-show-seller-info/icon.png // @icon64 https://github.com/TadWohlrapp/UserScripts/raw/master/amazon-show-seller-info/icon64.png // @author Tad Wohlrapp // @homepageURL https://github.com/TadWohlrapp/UserScripts/tree/master/amazon-show-seller-info // @version 1.1.1 // @supportURL https://github.com/TadWohlrapp/UserScripts/issues // @match https://smile.amazon.co.uk/* // @match https://www.amazon.co.uk/* // @match https://smile.amazon.de/* // @match https://www.amazon.de/* // @match https://www.amazon.es/* // @match https://www.amazon.fr/* // @match https://www.amazon.it/* // @compatible chrome Tested with Tampermonkey v4.9 and Violentmonkey v2.12.7 // @compatible firefox Tested with Greasemonkey v4.9 // @copyright 2020, Tad Wohlrapp (https://github.com/TadWohlrapp/UserScripts) // @license MIT // @downloadURL none // ==/UserScript== // ==OpenUserJS== // @author Taddiboy // ==/OpenUserJS== (function () { 'use strict'; const highlightedCountries = ['CN', 'HK']; // Country codes as per ISO 3166-1 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'] // 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() { 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)\/.*/)) { fetch(product.href).then(function (response) { if (response.ok) { return response.text(); } }).then(function (html) { const productPage = parse(html); 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')); fetch(thirdPartySeller.href).then(function (response) { if (response.ok) { return response.text(); } else if (response.status === 503) { throw new Error('Too many requests 🙄 Amazon blocked seller page'); } else { throw new Error(response.status); } }).then(function (html) { const sellerPage = parse(html); // Get seller rating let rating = sellerPage.getElementById('seller-feedback-summary'); 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); // Get seller country & flag const sellerUl = sellerPage.querySelectorAll('ul.a-unordered-list.a-nostyle.a-vertical'); //get all ul 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) { const 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 { console.info('Wait, that\'s illegal! 🚨 Seller "' + thirdPartySeller.textContent + '" (' + thirdPartySeller.href + ') has no valid imprint!'); } }).catch(function (err) { console.warn('Could not fetch seller data for "' + thirdPartySeller.textContent + '" (' + thirdPartySeller.href + '): ', err); }); } 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')); } }).catch(function (err) { // There was an error console.warn('Something went wrong fetching ' + product.href, err); }); } } } // 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(html) { const parser = new DOMParser(); return parser.parseFromString(html, 'text/html'); } function addGlobalStyle(css) { const head = document.getElementsByTagName('head')[0]; if (!head) { return; } const style = document.createElement('style'); style.innerHTML = css; head.appendChild(style); } // Add Google's own CSS used for image dimensions addGlobalStyle(` .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; } `); } })();