Skip to content

Instantly share code, notes, and snippets.

@elado
Last active November 6, 2026 06:57
Show Gist options
  • Select an option

  • Save elado/69fa611d84305dea4b38801880743928 to your computer and use it in GitHub Desktop.

Select an option

Save elado/69fa611d84305dea4b38801880743928 to your computer and use it in GitHub Desktop.
American Express / Amex - Add all offers to card at once (bookmarklet)

American Express - Add all offers to card at once

If you own an AMEX card, you can add a bunch of offers to the card in this link: https://global.americanexpress.com/offers/eligible

There are many offers, and they change all the time. Instead of clicking "Add to card" repeatedly, I created this bookmarklet.

In Chrome, add a new bookmark (right click on bookmarks bar -> "Add Page...") with the following URL:

javascript:(()=>{let q=s=>[...document.querySelectorAll(s)],b=q('.offer-cta');if(!b.length)b=q('button,[role="button"]').filter(x=>{let l=(x.getAttribute('aria-label')||x.title||'').toLowerCase();return l.startsWith('add ')||l.includes(' add ')});if(!b.length)b=q('button').filter(x=>x.querySelector('svg')&&!x.textContent.trim()&&!['chat','search','menu'].some(w=>(x.getAttribute('aria-label')||x.title||'').toLowerCase().includes(w)));b=[...new Set(b)];if(!b.length)return alert('0 offers found.');console.log(`Found ${b.length} offers`);let c=()=>{let o=b.shift();if(!o)return alert('Finished adding offers!');o.scrollIntoView({behavior:'smooth',block:'center'});setTimeout(()=>{o.click();setTimeout(c,Math.random()*400+400)},300)};c();})();

Last updated: 10/27/26

Just run the bookmark while on the offers page, and watch the magic happens!

javascript:(()=>{let q=s=>[...document.querySelectorAll(s)],b=q('.offer-cta');if(!b.length)b=q('button,[role="button"]').filter(x=>{let l=(x.getAttribute('aria-label')||x.title||'').toLowerCase();return l.startsWith('add ')||l.includes(' add ')});if(!b.length)b=q('button').filter(x=>x.querySelector('svg')&&!x.textContent.trim()&&!['chat','search','menu'].some(w=>(x.getAttribute('aria-label')||x.title||'').toLowerCase().includes(w)));b=[...new Set(b)];if(!b.length)return alert('0 offers found.');console.log(`Found ${b.length} offers`);let c=()=>{let o=b.shift();if(!o)return alert('Finished adding offers!');o.scrollIntoView({behavior:'smooth',block:'center'});setTimeout(()=>{o.click();setTimeout(c,Math.random()*400+400)},300)};c();})();
javascript:(() => {
let btns = [...document.querySelectorAll('.offer-cta')];
if (btns.length === 0) {
btns = [...document.querySelectorAll('button, [role="button"]')].filter(b => {
let lbl = (b.getAttribute('aria-label') || b.title || "").toLowerCase();
return lbl.startsWith('add ') || lbl.includes(' add ');
});
}
if (btns.length === 0) {
btns = [...document.querySelectorAll('button')].filter(b =>
b.querySelector('svg') && !b.textContent.trim()
);
btns = btns.filter(b => {
let lbl = (b.getAttribute('aria-label') || b.title || "").toLowerCase();
return !lbl.includes('chat') && !lbl.includes('search') && !lbl.includes('menu');
});
}
btns = [...new Set(btns)];
console.log(`Found ${btns.length} offers to add.`);
if (btns.length === 0) {
alert('0 offers found. Amex may have deeply nested the buttons inside Shadow DOMs.');
return;
}
let c = () => {
let b = btns.shift();
if (!b) {
console.log('Finished adding offers!');
alert('Finished adding offers!');
return;
}
b.scrollIntoView({ behavior: 'smooth', block: 'center' });
setTimeout(() => {
b.click();
setTimeout(c, Math.random() * 400 + 400);
}, 300);
};
c();
})();
@samwathegreat

samwathegreat commented Dec 2, 2025 via email

Copy link
Copy Markdown

@samwathegreat

samwathegreat commented Dec 4, 2025 •

Copy link
Copy Markdown

FYI, here is the one-liner for your bookmarks. Credit to @feiyax

javascript:btns=[...document.querySelectorAll('button[title="add to list card"]')];c = () => {b = btns.pop();if (!b) return console.log('added all!');b.click();setTimeout(c, Math.random() * 1500 + 300);};c();

Working as of today, 12/4/25

@quankhuc

quankhuc commented Apr 6, 2026 •

Copy link
Copy Markdown

Credit to the script above. I updated the script to their newest layout and easier to read for a dev :)

javascript:(() => {
  const clickNext = () => {
    const b = document.querySelector('button[data-testid="merchantOfferListAddButton"]');
    if (!b) return console.log("added all!");
    b.click();
    setTimeout(clickNext, 20);
  };
 
  clickNext();
})();

@ashleyconnor

Copy link
Copy Markdown

Very nice @quankhuc - works on Firefox 158+

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment