mattwiebe.blog
mattwiebe.blog
@mattwiebe.blog@mattwiebe.blog

this blog is for testing fediverse integration from WordPress.com, but soon I can actually just use it!

63 posts
51 followers

UberEats Bookmarklet for “Don’t Replace”

Bookmarklets are one of the web’s superpowers, and agents make them so much easier!

I order groceries on UberEats from time to time and one thing that drives me insane is how I can’t make a default setting for “Don’t Replace” on my items. I almost never want the replacement that the shopper attempts. It also makes the shopper take longer.

Every item in a cart takes probably 30-45 seconds to update manually. There is no global default setting, it always defaults to “Replace with any similar item.” On my last order of around 30 items, I gave up halfway through, and got stuck with several replacements I didn’t want.

I know that this is scriptable, in theory. Before agents, this would take so much longer than doing it manually, so I wouldn’t have bothered.

So I opened the Claude extension in my browser and gave it a simple prompt:

I want you to pay attention to the XHR requests made to shift an item in my cart from “Replace with any similar item” to “don’t replace”
So that we can make a script to make that shift programattically for every item in my cart

Sonnet 4.6 nailed it, in one shot. Had it make a bookmarklet too. Anyone who wants it, grab it from the Gist or view it here:

javascript:(async()=>{const L=window.location.pathname.match(/^\/([a-z]{2}-[a-z]{2})\//)?.[1]??'en-US',B='https://www.ubereats.com/_p/api',H={'Content-Type':'application/json','x-csrf-token':'x'},d=await(await fetch(`${B}/getDraftOrdersByEaterUuidV1?localeCode=${L}`,{method:'POST',headers:H,body:'{}'})).json();if(d.status!=='success'||!d.data.draftOrders.length){alert('Could not fetch cart.');return;}const{uuid:dUUID,shoppingCart:{cartUuid:cUUID,items}}=d.data.draftOrders[0],toUpdate=items.filter(i=>i.fulfillmentIssueAction?.type!=='REMOVE_ITEM');console.log(`Updating ${toUpdate.length}/${items.length} items…`);let ok=0;for(const i of toUpdate){const r=await(await fetch(`${B}/updateItemInDraftOrderV2?localeCode=${L}`,{method:'POST',headers:H,body:JSON.stringify({draftOrderUUID:dUUID,cartUUID:cUUID,item:{uuid:i.uuid,shoppingCartItemUuid:i.shoppingCartItemUuid,storeUuid:i.storeUuid,sectionUuid:i.sectionUuid,subsectionUuid:i.subsectionUuid,price:i.price,title:i.title,quantity:i.quantity,customizations:i.customizations??{},specialInstructions:i.specialInstructions??'',imageURL:i.imageURL??'',fulfillmentIssueAction:{type:'REMOVE_ITEM',selectionSource:'CONSUMER_SELECTED',itemSubstitutes:[]}}})})).json();r.status==='success'?ok++:console.error(`Failed: ${i.title}`,r);await new Promise(r=>setTimeout(r,300));}alert(`Done! ${ok}/${toUpdate.length} items set to "Don't replace".`);})();
view raw bookmarklet.js hosted with ❤ by GitHub
(async function setAllItemsToDontReplace() {
const LOCALE = window.location.pathname.match(/^\/([a-z]{2}-[a-z]{2})\//)?.[1] ?? 'en-US';
const BASE_URL = 'https://www.ubereats.com/_p/api';
const HEADERS = { 'Content-Type': 'application/json', 'x-csrf-token': 'x' };
// 1. Fetch current draft order
const draftRes = await fetch(`${BASE_URL}/getDraftOrdersByEaterUuidV1?localeCode=${LOCALE}`, {
method: 'POST', headers: HEADERS, body: JSON.stringify({})
});
const draftData = await draftRes.json();
if (draftData.status !== 'success' || !draftData.data.draftOrders.length) {
console.error('Could not fetch draft orders:', draftData);
return;
}
const draftOrder = draftData.data.draftOrders[0];
const { uuid: draftOrderUUID, shoppingCart: { cartUuid: cartUUID, items } } = draftOrder;
// 2. Filter items that are NOT already "Don't replace"
const toUpdate = items.filter(item =>
item.fulfillmentIssueAction?.type !== 'REMOVE_ITEM'
);
console.log(`Updating ${toUpdate.length} of ${items.length} items to "Don't replace"…`);
// 3. Update each item sequentially
let successCount = 0;
for (const item of toUpdate) {
const res = await fetch(`${BASE_URL}/updateItemInDraftOrderV2?localeCode=${LOCALE}`, {
method: 'POST',
headers: HEADERS,
body: JSON.stringify({
draftOrderUUID,
cartUUID,
item: {
uuid: item.uuid,
shoppingCartItemUuid: item.shoppingCartItemUuid,
storeUuid: item.storeUuid,
sectionUuid: item.sectionUuid,
subsectionUuid: item.subsectionUuid,
price: item.price,
title: item.title,
quantity: item.quantity,
customizations: item.customizations ?? {},
specialInstructions: item.specialInstructions ?? '',
imageURL: item.imageURL ?? '',
fulfillmentIssueAction: {
type: 'REMOVE_ITEM',
selectionSource: 'CONSUMER_SELECTED',
itemSubstitutes: []
}
}
})
});
const data = await res.json();
if (data.status === 'success') { console.log(`✅ ${item.title}`); successCount++; }
else { console.error(`❌ ${item.title}`, data); }
await new Promise(r => setTimeout(r, 300));
}
console.log(`\nDone! ${successCount}/${toUpdate.length} items updated.`);
})();

Discover more from mattwiebe.blog

Subscribe now to keep reading and get access to the full archive.

Continue reading