NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Amazon URL canonicalizer // @author zfhrp // @description Replace Amazon product page url with canonical form (`https://amazon.co.jp/dp/XXXXXXXX/`) // @homepageURL https://openuserjs.org/users/zfhrp // @license MIT // @version 1.0.0 // @match *://*.amazon.co.jp/dp/* // @match *://*.amazon.co.jp/*/dp/* // @match *://*.amazon.co.jp/gp/product/* // @match *://*.amazon.co.jp/*/ASIN/* // @match *://*.amazon.com/dp/* // @match *://*.amazon.com/*/dp/* // @match *://*.amazon.com/gp/product/* // @match *://*.amazon.com/*/ASIN/* // @icon https://www.amazon.co.jp/favicon.ico // @run-at document-start // ==/UserScript== /** * get ASIN from page location. * ASIN is also known as productId and is some-digit alphanumeric ID. * @return {string|null} ASIN */ const getASIN = () => { const patterns = [ /(?:.+\/)?dp\/([^/?]+)/, /gp\/product\/([^/?]+)/, /ASIN\/([^/?]+)/, ]; for(const pattern of patterns){ const asin = location.href.match(pattern); if (asin) { return asin[1]; } } // cannot get ASIN return null; } const isCanonicalUrl = () => { const pathPattern = /^\/dp\/[a-zA-Z0-9]+\/?$/; return location.pathname.match(pathPattern) !== null; } const isGpProductUrl = () => { const pathPattern = /\/gp\/[a-zA-Z0-9-]+/; return location.pathname.match(pathPattern) !== null; } const ignorePattern = () => { return isGpProductUrl(); } /** * location.replace(canonicalURL) */ const canonicalize = () => { const asin = getASIN(); if (!asin) { return; } // i.e. https://www.amazon.co.jp/dp/XXXXXXXX/ const canonicalUrl = `${location.protocol}//${document.domain}/dp/${asin}/`; location.replace(canonicalUrl); } const main = () => { if (!ignorePattern() && !isCanonicalUrl()) { canonicalize(); } } main();