├── JS - Bookmarklet ├── Javascript └── README.md /JS - Bookmarklet: -------------------------------------------------------------------------------- 1 | javascript:(function(){const%20u=window.location.href;let%20r=false,d=1000;const%20p=document.createElement("div");p.innerHTML='

%F0%9F%9B%92%20Auto%20Add%20Offers

%E2%8F%B9%EF%B8%8F%20Status:%20Stopped

%F0%9F%94%84%20Offers%20Remaining:%20--

%E2%8F%B3%20Est.%20Time%20Left:%20--

SlowNormalFast

%E2%96%B6%20Start%E2%8F%B9%20Stop';document.body.appendChild(p);function%20c(a=0){if(!r){document.getElementById("status").innerText="%E2%8F%B9%EF%B8%8F%20Status:%20Stopped";return}const%20b=document.querySelectorAll('[data-cy="commerce-tile-button"]');if(b.length>0){const%20o=b.length,m=((o*(d/2))/1000).toFixed(0),x=((o*d)/1000).toFixed(0);document.getElementById("progress").innerText=`%F0%9F%94%84%20Offers%20Remaining:%20${o}`;document.getElementById("timeLeft").innerText=`%E2%8F%B3%20Est.%20Time%20Left:%20${m}-${x}%20sec`;document.getElementById("status").innerText="%E2%9C%85%20Status:%20Running...";console.log(`%F0%9F%93%8C%20Clicking%20an%20offer...%20(${o}%20remaining)`);const%20e=b[0];try{if(e&&typeof%20e.click==='function'){e.click()}else{console.log("%E2%9A%A0%EF%B8%8F%20Using%20fallback%20click%20method");const%20v=new%20MouseEvent('click',{view:window,bubbles:true,cancelable:true});e.dispatchEvent(v)}}catch(err){console.error("%E2%9D%8C%20Error%20clicking%20button:",err);if(a<3){console.log(`%E2%9A%A0%EF%B8%8F%20Click%20failed.%20Retrying%20(${a+1}/3)...`);setTimeout(()=>c(a+1),1000);return}}let%20k=Math.floor(Math.random()*(d/2))+d;setTimeout(()=>{console.log("%F0%9F%94%84%20Returning%20to%20original%20page...");window.location.href=u;let%20l=Math.floor(Math.random()*(d/2))+d;setTimeout(()=>{if(r){console.log("%E2%8F%B3%20Waiting%20before%20next%20click...");c()}},l)},k)}else{if(a<3){console.log(`%E2%9A%A0%EF%B8%8F%20No%20buttons%20detected.%20Retrying%20(${a+1}/3)...`);setTimeout(()=>c(a+1),2000)}else{console.log("%E2%9C%85%20All%20offers%20added!");document.getElementById("status").innerText="%E2%9C%85%20Status:%20Completed!";r=false}}}document.getElementById("start-btn").addEventListener("click",()=>{if(!r){r=true;c()}});document.getElementById("stop-btn").addEventListener("click",()=>{r=false;document.getElementById("status").innerText="%E2%8F%B9%EF%B8%8F%20Status:%20Stopped";console.log("%E2%8F%B9%EF%B8%8F%20Auto%20Add%20Offers%20script%20stopped.")});document.getElementById("speed-control").addEventListener("change",(e)=>{d=parseInt(e.target.value);console.log(`%E2%8F%A9%20Speed%20changed%20to:%20${e.target.options[e.target.selectedIndex].text}`)});console.log("%F0%9F%9A%80%20Auto%20Add%20Offers%20script%20loaded!")})(); 2 | -------------------------------------------------------------------------------- /Javascript: -------------------------------------------------------------------------------- 1 | (function () { 2 | const originalUrl = window.location.href; 3 | let isRunning = false; 4 | let delayTime = 1000; // Default to Fast (1 sec delay) 5 | 6 | // Create floating UI panel 7 | const panel = document.createElement("div"); 8 | panel.innerHTML = ` 9 |
17 |

🛒 Auto Add Offers

18 |

⏹️ Status: Stopped

19 |

🔄 Offers Remaining: --

20 |

⏳ Est. Time Left: --

21 | 22 | 27 |

28 | 29 | 30 |
31 | `; 32 | document.body.appendChild(panel); 33 | 34 | function clickAndReturn(attempts = 0) { 35 | if (!isRunning) { 36 | document.getElementById("status").innerText = "⏹️ Status: Stopped"; 37 | return; 38 | } 39 | 40 | const buttons = document.querySelectorAll('[data-cy="commerce-tile-button"]'); 41 | 42 | if (buttons.length > 0) { 43 | const offersLeft = buttons.length; 44 | const minTimeSec = ((offersLeft * (delayTime / 2)) / 1000).toFixed(0); 45 | const maxTimeSec = ((offersLeft * delayTime) / 1000).toFixed(0); 46 | 47 | document.getElementById("progress").innerText = `🔄 Offers Remaining: ${offersLeft}`; 48 | document.getElementById("timeLeft").innerText = `⏳ Est. Time Left: ${minTimeSec}-${maxTimeSec} sec`; 49 | document.getElementById("status").innerText = "✅ Status: Running..."; 50 | 51 | console.log(`📌 Clicking an offer... (${offersLeft} remaining)`); 52 | console.log(`⏳ Estimated time left: ${minTimeSec}-${maxTimeSec} seconds`); 53 | 54 | // FIX: Better click handling with error checking 55 | const button = buttons[0]; 56 | try { 57 | if (button && typeof button.click === 'function') { 58 | button.click(); 59 | } else { 60 | // Fallback: Try to trigger click event manually 61 | console.log("⚠️ Using fallback click method"); 62 | const clickEvent = new MouseEvent('click', { 63 | view: window, 64 | bubbles: true, 65 | cancelable: true 66 | }); 67 | button.dispatchEvent(clickEvent); 68 | } 69 | } catch (error) { 70 | console.error("❌ Error clicking button:", error); 71 | // If click fails, try next button 72 | if (attempts < 3) { 73 | console.log(`⚠️ Click failed. Retrying (${attempts + 1}/3)...`); 74 | setTimeout(() => clickAndReturn(attempts + 1), 1000); 75 | return; 76 | } 77 | } 78 | 79 | let backDelay = Math.floor(Math.random() * (delayTime / 2)) + delayTime; 80 | setTimeout(() => { 81 | console.log("🔄 Returning to original page..."); 82 | window.location.href = originalUrl; 83 | 84 | let reloadDelay = Math.floor(Math.random() * (delayTime / 2)) + delayTime; 85 | setTimeout(() => { 86 | if (isRunning) { 87 | console.log("⏳ Waiting before next click..."); 88 | clickAndReturn(); 89 | } 90 | }, reloadDelay); 91 | }, backDelay); 92 | } else { 93 | if (attempts < 3) { 94 | console.log(`⚠️ No buttons detected. Retrying (${attempts + 1}/3)...`); 95 | setTimeout(() => clickAndReturn(attempts + 1), 2000); 96 | } else { 97 | console.log("✅ All offers added! (or no more found)"); 98 | document.getElementById("status").innerText = "✅ Status: Completed!"; 99 | isRunning = false; 100 | } 101 | } 102 | } 103 | 104 | document.getElementById("start-btn").addEventListener("click", () => { 105 | if (!isRunning) { 106 | isRunning = true; 107 | clickAndReturn(); 108 | } 109 | }); 110 | 111 | document.getElementById("stop-btn").addEventListener("click", () => { 112 | isRunning = false; 113 | document.getElementById("status").innerText = "⏹️ Status: Stopped"; 114 | console.log("⏹️ Auto Add Offers script stopped."); 115 | }); 116 | 117 | document.getElementById("speed-control").addEventListener("change", (event) => { 118 | delayTime = parseInt(event.target.value); 119 | console.log(`⏩ Speed changed to: ${event.target.options[event.target.selectedIndex].text}`); 120 | }); 121 | 122 | console.log("🚀 Auto Add Offers script loaded! Use the floating panel to start."); 123 | })(); 124 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🛒 Auto Add Chase Offers - JavaScript Automation Script 2 | 3 | This JavaScript script **automates clicking "Add Offer" buttons** on a webpage, ensuring that all available offers are selected **without manual effort**. 4 | This is designed for adding offers to your Chase credit card: 5 | https://secure.chase.com/web/auth/dashboard#/dashboard/merchantOffers/offerCategoriesPage?offerCategoryName=ALL 6 | 7 | ## DO NOT RUN JS ONCE AUTHENTICATED TO A BANKING PAGE UNLESS YOU KNOW WHAT IT DOES 8 | 9 | --- 10 | 11 | ## 📌 Features 12 | - ✅ **Automatically detects and clicks** all "Add Offer" buttons. 13 | - ✅ **Floating UI panel** with Start/Stop buttons for easy control. 14 | - ✅ **Tracks real-time progress** (remaining offers, estimated time left). 15 | - ✅ **Speed settings** (**Slow, Normal, Fast**) — now defaults to **Fast mode** ⚡. 16 | - ✅ **Mimics human-like behavior** with randomized delays (1-3 sec). 17 | - ✅ **Stops at any time** with the Stop button. 18 | - ✅ **Retry mechanism** ensures all offers are truly added before stopping. 19 | 20 | --- 21 | 22 | ## 🖥️ How It Works 23 | 1. **Finds all "Add Offer" buttons** using their `data-cy` attribute. 24 | 2. **Clicks the first available offer** and waits 1-3 seconds. 25 | 3. **Returns to the original page** after clicking an offer. 26 | 4. **Waits for the page to reload** before clicking the next button. 27 | 5. **Updates the floating UI panel** with real-time progress. 28 | 6. **Retries if no buttons are found**, ensuring every offer is added. 29 | 7. **Repeats the process** until all offers are added or stopped. 30 | 31 | --- 32 | 33 | ## 🛠 How to Use It 34 | 1. Open your browser and navigate to the webpage containing the offers. 35 | 2. Open the **Developer Console**: 36 | - **Chrome:** `Ctrl + Shift + J` (Windows) or `Cmd + Option + J` (Mac) 37 | - **Firefox:** `Ctrl + Shift + K` (Windows) or `Cmd + Option + K` (Mac) 38 | - **Edge:** `F12` → **Console** 39 | 3. **Copy & paste the script** below into the console and press **Enter**. 40 | 4. A **floating control panel** will appear on the page. 41 | 5. Click **"Start"** to begin adding offers. 42 | 6. Click **"Stop"** anytime to halt the script. 43 | 7. Adjust the **speed setting** if needed (defaults to Fast). 44 | 45 | --- 46 | 47 | ## 📝 Copy & Paste This Script 48 | ```javascript 49 | (function () { 50 | const originalUrl = window.location.href; 51 | let isRunning = false; 52 | let delayTime = 1000; // Default to Fast (1 sec delay) 53 | 54 | // Create floating UI panel 55 | const panel = document.createElement("div"); 56 | panel.innerHTML = ` 57 |
65 |

🛒 Auto Add Offers

66 |

⏹️ Status: Stopped

67 |

🔄 Offers Remaining: --

68 |

⏳ Est. Time Left: --

69 | 70 | 75 |

76 | 77 | 78 |
79 | `; 80 | document.body.appendChild(panel); 81 | 82 | function clickAndReturn(attempts = 0) { 83 | if (!isRunning) { 84 | document.getElementById("status").innerText = "⏹️ Status: Stopped"; 85 | return; 86 | } 87 | 88 | const buttons = document.querySelectorAll('[data-cy="commerce-tile-button"]'); 89 | 90 | if (buttons.length > 0) { 91 | const offersLeft = buttons.length; 92 | const minTimeSec = ((offersLeft * (delayTime / 2)) / 1000).toFixed(0); 93 | const maxTimeSec = ((offersLeft * delayTime) / 1000).toFixed(0); 94 | 95 | document.getElementById("progress").innerText = `🔄 Offers Remaining: ${offersLeft}`; 96 | document.getElementById("timeLeft").innerText = `⏳ Est. Time Left: ${minTimeSec}-${maxTimeSec} sec`; 97 | document.getElementById("status").innerText = "✅ Status: Running..."; 98 | 99 | console.log(`📌 Clicking an offer... (${offersLeft} remaining)`); 100 | console.log(`⏳ Estimated time left: ${minTimeSec}-${maxTimeSec} seconds`); 101 | 102 | // FIX: Better click handling with error checking 103 | const button = buttons[0]; 104 | try { 105 | if (button && typeof button.click === 'function') { 106 | button.click(); 107 | } else { 108 | // Fallback: Try to trigger click event manually 109 | console.log("⚠️ Using fallback click method"); 110 | const clickEvent = new MouseEvent('click', { 111 | view: window, 112 | bubbles: true, 113 | cancelable: true 114 | }); 115 | button.dispatchEvent(clickEvent); 116 | } 117 | } catch (error) { 118 | console.error("❌ Error clicking button:", error); 119 | // If click fails, try next button 120 | if (attempts < 3) { 121 | console.log(`⚠️ Click failed. Retrying (${attempts + 1}/3)...`); 122 | setTimeout(() => clickAndReturn(attempts + 1), 1000); 123 | return; 124 | } 125 | } 126 | 127 | let backDelay = Math.floor(Math.random() * (delayTime / 2)) + delayTime; 128 | setTimeout(() => { 129 | console.log("🔄 Returning to original page..."); 130 | window.location.href = originalUrl; 131 | 132 | let reloadDelay = Math.floor(Math.random() * (delayTime / 2)) + delayTime; 133 | setTimeout(() => { 134 | if (isRunning) { 135 | console.log("⏳ Waiting before next click..."); 136 | clickAndReturn(); 137 | } 138 | }, reloadDelay); 139 | }, backDelay); 140 | } else { 141 | if (attempts < 3) { 142 | console.log(`⚠️ No buttons detected. Retrying (${attempts + 1}/3)...`); 143 | setTimeout(() => clickAndReturn(attempts + 1), 2000); 144 | } else { 145 | console.log("✅ All offers added! (or no more found)"); 146 | document.getElementById("status").innerText = "✅ Status: Completed!"; 147 | isRunning = false; 148 | } 149 | } 150 | } 151 | 152 | document.getElementById("start-btn").addEventListener("click", () => { 153 | if (!isRunning) { 154 | isRunning = true; 155 | clickAndReturn(); 156 | } 157 | }); 158 | 159 | document.getElementById("stop-btn").addEventListener("click", () => { 160 | isRunning = false; 161 | document.getElementById("status").innerText = "⏹️ Status: Stopped"; 162 | console.log("⏹️ Auto Add Offers script stopped."); 163 | }); 164 | 165 | document.getElementById("speed-control").addEventListener("change", (event) => { 166 | delayTime = parseInt(event.target.value); 167 | console.log(`⏩ Speed changed to: ${event.target.options[event.target.selectedIndex].text}`); 168 | }); 169 | 170 | console.log("🚀 Auto Add Offers script loaded! Use the floating panel to start."); 171 | })(); 172 | --------------------------------------------------------------------------------