├── 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--
';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 |
--------------------------------------------------------------------------------