Turns the cart or product page you're on into rows you paste straight into the procurement sheet (columns A–I). Works on McMaster-Carr, Amazon, and any Shopify store (WCP, AndyMark, ThriftyBot…).
Ctrl/Cmd + Shift + B.Desktop only for now. Phones can't run bookmarklets reliably (and stores like McMaster block hosted scripts via CSP), so the mobile path is parked. Do procurement entry from a computer.
javascript:(()=>{var et=Object.defineProperty;var C=(t,e)=>{for(var n in e)et(t,n,{get:e[n],enumerable:!0})};var k={};C(k,{key:()=>ot,scrapeCart:()=>it,scrapeProduct:()=>at});function l(t,e=0){if(typeof t=="number")return Number.isFinite(t)?t:e;if(t==null)return e;let n=parseFloat(String(t).replace(/[^0-9.\-]/g,""));return Number.isFinite(n)?n:e}function h(t){return Math.round((Number(t)+Number.EPSILON)*100)/100}function _(t=new Date){return`${t.getMonth()+1}/${t.getDate()}/${t.getFullYear()}`}var nt=/^(utm_|ref$|ref_|_ga$|gclid|fbclid|mc_[ce]id|psc$|th$)/i;function T(t,e){if(!t)return"";try{let n=new URL(t,e);for(let o of[...n.searchParams.keys()])nt.test(o)&&n.searchParams.delete(o);return n.toString()}catch{return String(t).trim()}}function S(t){return String(t||"").replace(/^www\./,"").toLowerCase()}var ot="shopify",rt=/\(([A-Z]{2,5}-\d{3,5})\)/,R=/\$\s?([\d,]+\.\d{2})/;async function it(t){return((await t.fetch("/cart.js").then(n=>n.json())).items||[]).map(n=>({partNumber:n.sku||"",description:U(n.product_title||n.title,n.variant_title),quantity:n.quantity,unitCost:I(n.final_price??n.price),weblink:lt(t,n.url)}))}async function at(t){let e=ct(t);if(e.length)return e;let n=st(t.location.pathname);if(!n)throw new Error("Not a Shopify product page.");let{product:o}=await t.fetch(`/products/${n}.json`).then(i=>i.json()),r=ut(o,t.location.search);return[{partNumber:r.sku||"",description:U(o.title,r.title),quantity:1,unitCost:I(r.price),weblink:pt(t,n,r.id)}]}function ct(t){let e=[],n=new Set;for(let o of t.document.querySelectorAll("input.product-custom-option")){if(!o.checked)continue;let r=o.closest(".admin__field-option");if(!r||r.classList.contains("ihidden"))continue;let i=(r.textContent||"").replace(/\s+/g," ").trim(),a=rt.exec(i);if(!a||n.has(a[1]))continue;n.add(a[1]);let c=R.exec(i.slice(a.index+a[0].length))||R.exec(i),p=r.querySelector('input.option-qty, input[name^="options_qty"]');e.push({partNumber:a[1],description:i.slice(0,a.index).trim(),quantity:p?l(p.value,1):1,unitCost:c?l(c[1]):0,weblink:t.location.href})}return e}function I(t){if(typeof t=="number")return t/100;let e=parseFloat(t);return Number.isFinite(e)?e:0}function U(t,e){let n=(e||"").trim();return n&&n.toLowerCase()!=="default title"?`${t} (${n})`:t||""}function st(t){let e=/\/products\/([^/?%23]+)/.exec(t||"");return e?e[1]:null}function ut(t,e){let n=t.variants||[],o=new URLSearchParams(e||"").get("variant");if(o){let r=n.find(i=>String(i.id)===String(o));if(r)return r}return n[0]||{}}function pt(t,e,n){let o=`${t.location.origin}/products/${e}`;return n?`${o}?variant=${n}`:o}function lt(t,e){try{return new URL(e,t.location.origin).toString()}catch{return e||""}}var $={};C($,{key:()=>dt,scrapeCart:()=>ft,scrapeProduct:()=>gt});var dt="amazon",mt=/\/(?:dp|gp\/product|gp\/aw\/d)\/([A-Z0-9]{10})/i;function ft(t){let e=t.document,n=e.querySelector('%23sc-active-cart, [data-name="Active Items"]')||e,o=[...n.querySelectorAll(".sc-list-item[data-asin], [data-asin][data-itemtotal]")];o.length||(o=[...n.querySelectorAll("[data-asin]")]);let r=new Set,i=[];for(let a of o){let c=a.getAttribute("data-asin");!c||r.has(c)||(r.add(c),i.push({partNumber:c,description:b(a,[".sc-product-title",".a-truncate-full",".sc-product-link","a .a-link-normal"]),quantity:yt(a),unitCost:l(b(a,[".sc-product-price",".sc-badge-price-to-pay .a-offscreen",".a-price .a-offscreen",".sc-price"])),weblink:H(t,c)}))}return i}function gt(t){let e=t.document,n=xt(t)||ht(e,["%23ASIN","input%23ASIN","[data-asin]"],"value","data-asin");return[{partNumber:n||"",description:b(e,["%23productTitle","%23title"]),quantity:1,unitCost:l(b(e,["%23corePriceDisplay_desktop_feature_div .a-offscreen","%23corePrice_feature_div .a-offscreen",".a-price .a-offscreen","%23priceblock_ourprice","%23price"])),weblink:n?H(t,n):t.location.href}]}function yt(t){let e=t.querySelector('input.sc-quantity-textfield, input[name="quantity"]');if(e&&e.value)return l(e.value,1);let n=t.getAttribute("data-quantity");if(n)return l(n,1);let o=t.querySelector("select option[selected], .a-dropdown-prompt");return o?l(o.textContent,1):1}function xt(t){let e=mt.exec(t.location.pathname||t.location.href||"");return e?e[1]:null}function H(t,e){return`${t.location.origin}/dp/${e}`}function b(t,e){for(let n of e){let o=t.querySelector(n),r=o&&o.textContent?o.textContent.trim():"";if(r)return r}return""}function ht(t,e,...n){for(let o of e){let r=t.querySelector(o);if(r)for(let i of n){let a=i==="value"?r.value:r.getAttribute(i);if(a)return a}}return""}var A={};C(A,{key:()=>bt,scrapeCart:()=>qt,scrapeProduct:()=>Ct});var bt="mcmaster",wt=/\b\d{3,6}[A-Z]\d{2,6}[A-Z0-9]*\b/,D=/^\/(\d{3,6}[A-Z]\d{2,6}[A-Z0-9]*)\/?$/i,vt=/\$\s?([\d,]+\.\d{2})/;async function qt(t){await O(t);let e=t.document,n=[...e.querySelectorAll("input.line-part-number-input")].map(p=>(p.value||"").trim().toUpperCase()),o=[...e.querySelectorAll("input.line-quantity-input")].map(p=>l(p.value,1)),r=[...e.querySelectorAll(".line-total-price")].map(p=>B(p.textContent)),i=St(e),a=Math.min(n.length,o.length,r.length),c=[];for(let p=0;p<a;p++){let m=n[p];if(!m)continue;let f=o[p];c.push({partNumber:m,description:i[m]||"",quantity:f,unitCost:f>0?r[p]/f:0,weblink:j(t,m)})}return c}async function Ct(t){await O(t);let e=t.document,n=kt(t)||$t(e);return[{partNumber:n||"",description:At(e),quantity:1,unitCost:B((e.querySelector('[class*="Price" i], [class*="price" i]')||e.body||{}).textContent),weblink:n?j(t,n):t.location.href}]}function St(t){let e={};for(let n of t.querySelectorAll("a[href]")){let o=D.exec(n.getAttribute("href")||"");if(!o)continue;let r=o[1].toUpperCase(),i=(n.textContent||"").trim();i&&i.toUpperCase()!==r&&!e[r]&&(e[r]=i)}return e}function B(t){let e=vt.exec(t||"");return e?l(e[1]):0}function kt(t){let e=D.exec(t.location.pathname||"");return e?e[1].toUpperCase():null}function $t(t){let e=wt.exec(t.title||"");return e?e[0].toUpperCase():null}function At(t){let e=t.querySelector("h1");return(e&&e.textContent.trim()||t.title||"").replace(/\s*\|\s*McMaster-?Carr\s*$/i,"").trim()}function j(t,e){return`${t.location.origin}/${e}/`}function O(t){let e=t.window;return!e||typeof e.requestAnimationFrame!="function"?Promise.resolve():new Promise(n=>{let o=0,r=()=>{t.document.querySelector("input.line-part-number-input, a[href]")||o++>10?n():e.requestAnimationFrame(r)};r()})}var Nt={"wcproducts.com":"WCP","andymark.com":"Andy Mark","thethriftybot.com":"Thrifty Bot"};function V(t){let e=S(t);return/(^|\.)amazon\./.test(e)?"amazon":/(^|\.)mcmaster\.com$/.test(e)?"mcmaster":"shopify"}function Z(t){let e=S(t);return Nt[e]||e.split(".")[0]}var K={amazon:"Amazon",mcmaster:"McMaster Carr"};var Ft={shopify:k,amazon:$,mcmaster:A};function Y(t){let e=V(t.location.hostname),n=e==="shopify"?Z(t.location.hostname):K[e];return{adapter:Ft[e],key:e,mode:Lt(e,t),storeName:n}}function Lt(t,e){let n=e.location.pathname||"";return t==="amazon"?/\/(?:dp|gp\/product|gp\/aw\/d)\//i.test(n)?"product":"cart":t==="mcmaster"?/^\/\d{3,6}[A-Z]\d{2,6}[A-Z0-9]*\/?$/i.test(n)?"product":"cart":/\/products\//.test(n)?"product":"cart"}function G(t,e={}){let n=e.requestDate||_(),o=e.requestor||"";return(t||[]).map(r=>{let i=l(r.quantity,1),a=h(l(r.unitCost,0));return{requestDate:n,requestor:o,partNumber:w(r.partNumber),description:w(r.description),quantity:i,unitCost:a,extendedCost:h(i*a),storeName:w(r.storeName)||w(e.storeName),weblink:T(r.weblink)}})}function N(t){return t.quantity=l(t.quantity,1),t.extendedCost=h(t.quantity*l(t.unitCost,0)),t}function w(t){return(t==null?"":String(t)).replace(/\s+/g," ").trim()}var W=["requestDate","requestor","partNumber","description","quantity","unitCost","extendedCost","storeName","weblink"];function x(t){return(t||[]).map(e=>W.map(n=>J(e[n])).join(" ")).join(`
`)}function F(t){let e=n=>`<tr>${W.map(o=>`<td>${zt(J(n[o]))}</td>`).join("")}</tr>`;return`<table>${(t||[]).map(e).join("")}</table>`}function J(t){return t==null?"":String(t).replace(/[\t\r\n]+/g," ").trim()}function zt(t){return String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function Mt(){return{document,window,location:window.location,fetch:(...t)=>window.fetch(...t)}}async function Q(t={}){let e=t.ctx||Mt(),{adapter:n,key:o,mode:r,storeName:i}=Y(e),a=r==="product"?await n.scrapeProduct(e):await n.scrapeCart(e),c=G(a,{storeName:i,requestor:t.requestor,requestDate:t.requestDate});return{rows:c,tsv:x(c),mode:r,storeName:i,store:o,count:c.length}}var X=`<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1080 1080" xml:space="preserve">
<style type="text/css">
.st0{fill:currentColor;}
</style>
<g>
<path class="st0" d="M863.23,340.9l45.78-142.14l-56.61-67.94h-77.76l-63.7,62.43l-171.34,0.65l-166.64-0.63l-0.14-0.1l-0.07,0.1
l-4.5-0.02l-63.7-62.43H226.8l-56.61,67.94l45.78,142.14L96.55,596.21l167.7,318.59l4.34,0.47
c105.84,11.52,192.42,19.1,271.01,18.69c2.09,0.01,4.16,0.02,6.26,0.02c76.91,0,161.72-7.49,264.75-18.71l4.34-0.47l167.7-318.59
L863.23,340.9z M962.52,591.88l-126.34,55.91l23.8-275.14L962.52,591.88z M781.34,147.22h63.38l45.91,55.11l-39.89,123.85
L725.96,201.49L781.34,147.22z M713.61,212.34l132.32,132.22L818.86,657.6l-78.9,93.52V543L547.93,440.03V324.62L713.61,212.34z
M539.57,210.3l148.66-0.57L539.81,310.31L396.47,209.75L539.57,210.3z M281.83,467.05l56.93,83.2v200.3l-78.42-92.95
l-16.48-190.55H281.83z M282.02,450.65h-39.59l-9.18-106.09l13.78-13.77l80.02,32.09L282.02,450.65z M531.53,324.53v102.65
L259.66,318.18l108.4-108.32L531.53,324.53z M188.57,202.32l45.91-55.11h63.38l55.38,54.27L228.45,326.17L188.57,202.32z
M219.22,372.65l23.8,275.14l-126.34-55.91L219.22,372.65z M274.7,899.43l-150.76-286.4l123.4,54.61l208.99,247.71
C401.75,912.41,342.18,906.75,274.7,899.43z M539.64,917.55h-0.04h-0.04c-19.7,0.1-39.94-0.31-60.87-1.16L355.16,770V556.63
l187.12-101.01l181.28,97.2v217.75L600.51,916.4C579.57,917.25,559.34,917.66,539.64,917.55z M804.5,899.43
c-67.48,7.31-127.05,12.98-181.64,15.91l209-247.71l123.4-54.61L804.5,899.43z"/>
<polygon class="st0" points="432.03,588.89 399.18,643.26 428.03,643.26 477.4,708.06 479.09,620.62 603.42,620.62 605.12,708.06
653.72,643.04 681.68,643.04 640.62,588.89 "/>
<polygon class="st0" points="600.68,813.02 561.33,813.02 519.31,813.02 479.96,813.02 450.61,766.53 437.3,788.72 476.7,865.62
519.31,865.62 561.33,865.62 611.85,865.62 643.34,788.72 630.03,766.53 "/>
<path class="st0" d="M488.88,525.54l46.67,27.03c3.47,2.14,7.85,2.14,11.32,0l46.67-27.59c6.71-4.13,6.05-14.1-1.14-17.31
l-51.18-27.36l-51.18,27.92C482.83,511.45,482.17,521.41,488.88,525.54z"/>
<polygon class="st0" points="679.38,441.69 641.81,424.82 608.63,452.08 648.32,473.94 "/>
</g>
</svg>
`;var z="procurement-scraper-overlay",tt="procReq.requestor",Pt="Manrope,-apple-system,system-ui,Segoe UI,Roboto,sans-serif",v={gold:"%23F0B842",goldHover:"%23E0A832",green:"%237CD49B",red:"%23E85D5D"},u={card:`box-sizing:border-box;width:min(420px,92vw);max-height:80vh;overflow:auto;background:%2315203F;color:%23F5F1E8;border:1px solid rgba(255,255,255,.14);border-radius:10px;box-shadow:0 30px 80px rgba(0,0,0,.5);padding:14px;font:13px/1.45 ${Pt};`,head:"display:flex;align-items:center;gap:8px;margin-bottom:10px;",mark:"color:%23F5F1E8;display:flex;flex:0 0 auto;",count:"font-size:15px;font-weight:700;",sub:"color:rgba(245,241,232,.62);text-transform:capitalize;",close:"margin-left:auto;border:0;background:none;font-size:20px;line-height:1;cursor:pointer;color:rgba(245,241,232,.38);",reqLabel:"display:block;color:rgba(245,241,232,.62);margin-bottom:10px;",reqInput:"display:block;width:100%25;margin-top:3px;padding:6px 8px;background:%23070F22;color:%23F5F1E8;border:1px solid rgba(255,255,255,.14);border-radius:6px;box-sizing:border-box;font:inherit;",row:"display:flex;align-items:center;gap:8px;padding:7px 0;border-top:1px solid rgba(255,255,255,.07);",main:"flex:1;min-width:0;",desc:"white-space:nowrap;overflow:hidden;text-overflow:ellipsis;",meta:"color:rgba(245,241,232,.38);font-size:11px;",qty:"width:52px;padding:4px;background:%23070F22;color:%23F5F1E8;border:1px solid rgba(255,255,255,.14);border-radius:6px;font:inherit;text-align:center;box-sizing:border-box;",ext:"width:72px;text-align:right;font-variant-numeric:tabular-nums;",actions:"display:flex;align-items:center;gap:10px;margin-top:12px;",copy:"background:%23F0B842;color:%230A1633;border:0;border-radius:7px;padding:8px 14px;font:inherit;font-weight:700;cursor:pointer;",status:"font-size:12px;",msg:"padding:6px 2px;"};_t().catch(t=>alert("Add to Procurement failed: "+(t&&t.message?t.message:t)));async function _t(){let t=document.getElementById(z);if(t){t.remove();return}let e=It();L(e,"Reading this page\u2026");try{let n=localStorage.getItem(tt)||"",o=await Q({requestor:n});if(!o.count){L(e,`No items found on this ${o.mode==="product"?"product page":"cart"} (${o.storeName}).`);return}Tt(e,o,n)}catch(n){L(e,`Couldn't scrape this page: ${n&&n.message?n.message:n}`)}}function Tt(t,e,n){t.textContent="";let o=e.rows,r=s("button",u.close,"\xD7");r.onclick=()=>document.getElementById(z)?.remove();let i=s("div",u.head);i.append(Ut(),s("span",u.count,`${e.count} item${e.count===1?"":"s"}`),s("span",u.sub,`${e.storeName} \xB7 ${e.mode}`),r);let a=s("label",u.reqLabel,"Requestor"),c=s("input",u.reqInput);c.type="text",c.placeholder="Your name",c.value=n,a.append(c);let p=s("div","");o.forEach(d=>{let g=s("div",u.main);g.append(s("div",u.desc,d.description||d.partNumber||"(no description)"),s("div",u.meta,`${d.partNumber||"\u2014"} \xB7 $${d.unitCost.toFixed(2)} ea`));let y=s("input",u.qty);y.type="number",y.min="0",y.step="1",y.value=String(d.quantity);let E=s("div",u.ext,`$${d.extendedCost.toFixed(2)}`);y.addEventListener("input",()=>{d.quantity=y.value,N(d),E.textContent=`$${d.extendedCost.toFixed(2)}`});let P=s("div",u.row);P.append(g,y,E),p.append(P)});let m=s("button",u.copy,"Copy rows");m.onmouseenter=()=>{m.style.background=v.goldHover},m.onmouseleave=()=>{m.style.background=v.gold};let f=s("span",u.status,""),M=s("div",u.actions);M.append(m,f);let q=d=>o.forEach(g=>g.requestor=d);q(n),c.addEventListener("input",()=>q(c.value.trim())),m.onclick=async()=>{let d=c.value.trim();d&&localStorage.setItem(tt,d),q(d);let g=await Rt(o);f.textContent=g?`Copied ${o.length} row${o.length===1?"":"s"} \u2014 paste into the sheet`:"Copy failed \u2014 try again",f.style.color=g?v.green:v.red},t.append(i,a,p,M)}async function Rt(t){let e=x(t);try{if(window.ClipboardItem&&navigator.clipboard&&navigator.clipboard.write)return await navigator.clipboard.write([new ClipboardItem({"text/plain":new Blob([e],{type:"text/plain"}),"text/html":new Blob([F(t)],{type:"text/html"})})]),!0}catch{}try{return await navigator.clipboard.writeText(e),!0}catch{}try{let n=document.createElement("textarea");n.value=e,n.style.cssText="position:fixed;left:-9999px;top:0",document.body.appendChild(n),n.focus(),n.select();let o=document.execCommand("copy");return n.remove(),o}catch{return!1}}function It(){let t=s("div","position:fixed;inset:auto 16px 16px auto;z-index:2147483647;margin:0;padding:0;border:0;background:transparent;max-width:92vw;");t.id=z;let e=t.attachShadow({mode:"open"}),n=s("div",u.card);if(e.append(n),(document.body||document.documentElement).append(t),typeof t.showPopover=="function"){t.setAttribute("popover","manual");try{t.showPopover()}catch{}}return n}function L(t,e){t.textContent="",t.append(s("div",u.msg,e))}function s(t,e,n){let o=document.createElement(t);return e&&(o.style.cssText=e),n!=null&&(o.textContent=n),o}function Ut(){let t=s("span",u.mark);t.innerHTML=X;let e=t.querySelector("svg");return e&&(e.setAttribute("width","16"),e.setAttribute("height","16"),e.style.display="block"),t}})();