// ==UserScript==
// @name Amazon Enhancer: Monthly + ReviewMeta + Camel + Keepa + UI + Dark + Review Highlights
// @namespace Eliminater74
// @version 1.4.2
// @description Highlights monthly payments, adds ReviewMeta, CamelCamelCamel, Keepa, sticky UI, themes, ad hiding, and more for Amazon users. Gear icon is now moveable again.
// @author Eliminater74
// @license MIT
// @match https://www.amazon.com/*
// @match https://www.amazon.co.uk/*
// @match https://www.amazon.de/*
// @match https://www.amazon.fr/*
// @match https://www.amazon.it/*
// @match https://www.amazon.es/*
// @match https://www.amazon.ca/*
// @match https://smile.amazon.com/*
// @grant GM_xmlhttpRequest
// @connect reviewmeta.com
// @run-at document-end
// ==/UserScript==
(function () {
'use strict';
const SETTINGS_KEY = 'amazonEnhancerSettings';
const defaultSettings = {
showReviewMeta: true,
showCamel: true,
showKeepa: true,
theme: 'auto',
highlightBestReviews: true,
hideAds: true,
showSoldBy: true,
stickyPriceBox: true,
autoSortReviews: true,
expandReviewsQA: true,
highlightMonthlyPayments: true,
filterOnlyMonthly: false
};
const settings = JSON.parse(localStorage.getItem(SETTINGS_KEY)) || defaultSettings;
const locale = getLocale();
const asin = findASIN();
if (asin) {
applyTheme(settings.theme);
if (settings.showReviewMeta) injectReviewMeta(asin, locale);
if (settings.showCamel) injectCamel(asin, locale);
if (settings.showKeepa) injectKeepa(asin, locale);
}
if (settings.highlightBestReviews) highlightReviews();
if (settings.hideAds) hideSponsored();
if (settings.showSoldBy) showSoldByBox();
if (settings.stickyPriceBox) makeStickyPriceBox();
if (settings.autoSortReviews) autoSortReviews();
if (settings.expandReviewsQA) expandSections();
if (settings.highlightMonthlyPayments || settings.filterOnlyMonthly) scanMonthlyPayments();
createToggleUI();
observePageChanges();
function saveSettings() {
localStorage.setItem(SETTINGS_KEY, JSON.stringify(settings));
}
function applyTheme(mode) {
const html = document.documentElement;
const theme = (mode === 'auto') ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : mode;
html.setAttribute('data-enhancer-theme', theme);
let style = document.getElementById('amazon-enhancer-theme-style');
if (style) style.remove();
style = document.createElement('style');
style.id = 'amazon-enhancer-theme-style';
style.textContent = `
[data-enhancer-theme="dark"] .amazon-enhancer-box {
background: #1d1d1d !important;
color: #f0f0f0 !important;
border-color: #555 !important;
}
[data-enhancer-theme="dark"] .amazon-enhancer-box a {
color: #7dddf2 !important;
}
[data-enhancer-theme="dark"] .amazon-enhancer-panel {
background: #2c2c2c !important;
color: #eee !important;
border-color: #555;
}
.highlighted-review {
border: 2px solid gold !important;
background-color: #fffbea !important;
}
.monthly-badge {
position: absolute;
top: 10px;
left: 10px;
background: #0099cc !important;
color: #ffffff !important;
padding: 2px 6px;
font-weight: bold;
font-size: 12px;
border-radius: 4px;
z-index: 2147483647 !important;
}
`;
document.head.appendChild(style);
}
function getLocale() {
const host = location.hostname;
if (host.includes(".co.uk")) return "uk";
if (host.includes(".de")) return "de";
if (host.includes(".fr")) return "fr";
if (host.includes(".es")) return "es";
if (host.includes(".it")) return "it";
if (host.includes(".ca")) return "ca";
return "us";
}
function findASIN() {
const match = location.href.match(/\/([A-Z0-9]{10})(?:[/?]|$)/);
if (match) return match[1];
const el = document.getElementById("ASIN") || document.querySelector('[name="ASIN.0"]');
return el?.value || null;
}
function injectCamel(asin, locale) {
const div = document.createElement("div");
div.className = 'amazon-enhancer-box';
div.innerHTML = `<a href='https://${locale}.camelcamelcamel.com/product/${asin}' target='_blank'>
<img src='https://charts.camelcamelcamel.com/${locale}/${asin}/amazon-new-used.png?force=1&zero=0&w=500&h=300' style='max-width:100%;'>
</a>`;
appendToTarget(div);
}
function injectKeepa(asin, locale) {
const div = document.createElement("div");
div.className = 'amazon-enhancer-box';
div.innerHTML = `<a href='https://keepa.com/#!product/1-${asin}' target='_blank'>
<img src='https://graph.keepa.com/pricehistory.png?used=1&amazon=1&new=1&domain=${locale}&asin=${asin}' style='max-width:100%;height:auto;'>
</a>`;
appendToTarget(div);
}
function injectReviewMeta(asin, locale) {
const url = `https://reviewmeta.com/amazon${locale === 'us' ? '' : '-' + locale}/${asin}`;
GM_xmlhttpRequest({
method: 'GET',
url,
onload: res => {
const doc = new DOMParser().parseFromString(res.responseText, "text/html");
const stars = doc.querySelector('#adjusted-rating-large')?.textContent?.trim();
const percent = Array.from(doc.querySelectorAll('small')).find(e => e.textContent.includes('potentially unnatural'))?.querySelector('span span')?.textContent?.trim();
const div = document.createElement('div');
div.className = 'amazon-enhancer-box';
div.style = 'margin-top:10px;padding:10px;border:1px solid #ccc;';
div.innerHTML = stars
? `<b>ReviewMeta Adjusted:</b> <span style='color:firebrick'>${stars}/5</span><br/>
<b>Fake Reviews:</b> <span style='color:firebrick'>${percent}</span><br/>
<a href='${url}' target='_blank' style='color:green;'>View on ReviewMeta</a>`
: `<b style='color:red;'>ReviewMeta data not found.</b><br/><a href='${url}' target='_blank'>Submit product</a>`;
appendToTarget(div);
}
});
}
function appendToTarget(el) {
const target = document.getElementById("unifiedPrice_feature_div") || document.getElementById("title")?.closest(".a-section");
if (target) target.appendChild(el);
}
function createToggleUI() {
const gear = document.createElement("div");
gear.innerText = "⚙️";
gear.id = "amazon-enhancer-gear";
gear.style.cssText = `
position: fixed;
bottom: 20px;
right: 20px;
width: 40px;
height: 40px;
font-size: 22px;
background: #222;
color: #fff;
border: 2px solid #888;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
cursor: move;
box-shadow: 0 0 12px rgba(0,0,0,0.8);
z-index: 2147483647;
`;
const panel = document.createElement("div");
panel.className = 'amazon-enhancer-panel';
panel.style.cssText = 'position:fixed;bottom:70px;right:20px;border:1px solid #ccc;padding:10px;border-radius:8px;z-index:99999;background:#fff;display:none;';
const toggles = [
['showReviewMeta', 'ReviewMeta'],
['showCamel', 'CamelCamelCamel'],
['showKeepa', 'Keepa'],
['highlightBestReviews', 'Highlight Best Reviews'],
['hideAds', 'Hide Sponsored Ads'],
['showSoldBy', 'Show Sold By'],
['stickyPriceBox', 'Sticky Price Box'],
['autoSortReviews', 'Auto Sort Reviews'],
['expandReviewsQA', 'Expand Q&A/Reviews'],
['highlightMonthlyPayments', 'Highlight Monthly Payments'],
['filterOnlyMonthly', 'Filter: Only Monthly Payment Items']
];
panel.innerHTML = toggles.map(([key, label]) =>
`<label><input type='checkbox' id='${key}' ${settings[key] ? 'checked' : ''}/> ${label}</label><br/>`
).join('') + `
<label>Theme:
<select id='themeSelect'>
<option value='auto' ${settings.theme === 'auto' ? 'selected' : ''}>Auto</option>
<option value='light' ${settings.theme === 'light' ? 'selected' : ''}>Light</option>
<option value='dark' ${settings.theme === 'dark' ? 'selected' : ''}>Dark</option>
</select>
</label>`;
toggles.forEach(([key]) => {
panel.querySelector(`#${key}`).addEventListener('change', e => {
settings[key] = e.target.checked;
saveSettings();
location.reload();
});
});
panel.querySelector('#themeSelect').addEventListener('change', e => {
settings.theme = e.target.value;
saveSettings();
applyTheme(settings.theme);
});
// Make gear draggable and clickable
let isDragging = false, offsetX = 0, offsetY = 0;
gear.addEventListener('mousedown', (e) => {
isDragging = true;
offsetX = e.clientX - gear.getBoundingClientRect().left;
offsetY = e.clientY - gear.getBoundingClientRect().top;
e.preventDefault();
});
document.addEventListener('mousemove', (e) => {
if (isDragging) {
gear.style.left = `${e.clientX - offsetX}px`;
gear.style.top = `${e.clientY - offsetY}px`;
gear.style.right = 'auto';
gear.style.bottom = 'auto';
}
});
document.addEventListener('mouseup', () => {
if (!isDragging) return;
isDragging = false;
});
gear.addEventListener('click', () => {
if (!isDragging) panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
});
gear.ondragstart = () => false;
document.body.appendChild(gear);
document.body.appendChild(panel);
}
function highlightReviews() {
const reviews = [...document.querySelectorAll('.review')];
const scored = reviews.map(el => {
const helpful = parseInt(el.innerText.match(/(\d+,?\d*) people found this helpful/)?.[1]?.replace(',', '') || '0');
const verified = el.innerHTML.includes('Verified Purchase') ? 5 : 0;
const longText = el.innerText.length > 500 ? 5 : 0;
const hasMedia = el.querySelectorAll('img').length ? 5 : 0;
return { el, score: helpful + verified + longText + hasMedia };
});
scored.sort((a, b) => b.score - a.score);
scored.slice(0, 3).forEach(r => r.el.classList.add('highlighted-review'));
}
function scanMonthlyPayments() {
const results = document.querySelectorAll('[data-component-type="s-search-result"], .s-result-item');
results.forEach(result => {
const text = result.innerText;
const match = /(?:\$\d+\.\d{2}\/month|\d+\s+monthly payments|\$[\d,]+(?:\.\d+)?\/mo\.?)/i.test(text);
const already = result.querySelector('.monthly-badge');
if (match) {
if (!already && settings.highlightMonthlyPayments) {
const badge = document.createElement('div');
badge.className = 'monthly-badge';
badge.textContent = '💳 Monthly Payments';
result.style.position = 'relative';
result.appendChild(badge);
}
result.style.display = '';
} else if (settings.filterOnlyMonthly) {
result.style.display = 'none';
} else {
result.style.display = '';
}
});
}
function hideSponsored() {
document.querySelectorAll("[data-component-type='sp-sponsored-result']").forEach(el => el.remove());
}
function showSoldByBox() {
const el = document.querySelector("#merchant-info");
if (el) el.style.border = "2px dashed orange";
}
function makeStickyPriceBox() {
const box = document.getElementById("corePrice_feature_div");
if (box) {
box.style.position = "sticky";
box.style.top = "0";
box.style.background = "#fff";
box.style.zIndex = 9999;
box.style.borderBottom = "2px solid #ccc";
}
}
function autoSortReviews() {
const sortSelect = document.querySelector('select[name="sortBy"]');
if (sortSelect) sortSelect.value = "recent";
}
function expandSections() {
document.querySelectorAll(".a-expander-prompt").forEach(e => e.click());
}
function observePageChanges() {
const observer = new MutationObserver(() => {
if (settings.highlightMonthlyPayments || settings.filterOnlyMonthly) scanMonthlyPayments();
});
observer.observe(document.body, { childList: true, subtree: true });
}
})();