DM Blog

Timesaving Shortcuts to Copy Delivery Orders from Square to DoorDash Drive

by #code #technology

I’ve been helping my friend Giorgio with all the technology[1] at Frank’s Pizza House for years. Most recently, I helped him setup on-demand deliveries through DoorDash Drive.[2]

After setting up his website to accept delivery orders via Square Online and training his staff on using the DoorDash Drive Portal to request drivers, I noticed that it was taking way too much time to transfer order information off the order tickets into the DoorDash Drive Portal. And like all manual data entry, it was prone to mistakes, especially during busy rushes.

My solution was to create a shortcut to automate copying the order information from Square and pasting it into the DoorDash Drive Portal. Apart from being less prone to errors, it’s saved him more than three work hours per week![3] That’s three+ hours that an employee can be doing something much more productive instead.

Here’s a video that demonstrates the shortcuts in action:

Download Shortcuts

The Shortcuts App by Apple comes installed by default on every iPhone and iPad, but if you’ve deleted it you can always re-install it from the App Store for free.

Here are the links to download the two shortcuts shown in the video:

Copy Delivery Info
Paste Delivery Info

Privacy & Security

As demonstrated in the video, installing the shortcuts requires the “Allow Untrusted Shortcuts” toggle to be enabled in Settings. However, before adding the shortcuts to your device, the Shortcuts app prompts you to review the full contents of the shortcuts so you can be sure that nothing malicious is going on, and you always have full access to see everything that the shortcut actually does.

As is evidenced by the lack of any analytics or trackers on my blog as well as all of my other websites, I never collect any information, personal or otherwise, because I don’t want your data. I don’t see your data as an asset; collecting data is an unnecessary liability.

As simply as I can describe it: when you tap the shortcut from the share menu in Safari, it grabs the order details from the Square website,[4] does some minor formatting for compatibility and copies this to your iPad’s clipboard before opening the DoorDash Drive Portal in a new tab. When you tap the “paste” shortcut, it takes the information copied to the iPad’s clipboard and pastes it onto the DoorDash Drive Portal. For additional security, Safari will ask for your permission to run JavaScript on the webpages the very first time each shortcut is run. Everything works locally on the device and nothing is transmitted to a third-party behind the scenes.

Technical Geekery

My original idea to automate this was to create an app on AWS Lambda that would use the Square API to automatically get notified of all new orders via a Webhook, then filter the data to get only delivery orders, request the order details and use that to automatically request a DoorDash Drive driver through their API. By the time the order ticket prints and the order is marked “in progress,” the delivery would already be scheduled with DoorDash Drive according to the delivery time quoted on the order.

The problem with that idea was threefold:

  1. Square’s API doesn’t have access to the Order ID printed on the ticket because that’s a separate ID generated by Square Online, formerly Weebly.
  2. Weebly does have a public REST API, but unfortunately it has been deprecated and you can’t sign up for access anymore.
  3. While it looks like DoorDash might be working on a Drive API, there’s no public API yet, and therefore, no way to programatically request delivery drivers.

The above method would be better than using iOS Shortcuts in several ways: by using APIs directly, it would make it more future-proof and not prone to errors should the Square or DoorDash Drive webpages ever change; it would allow me distribute it as an app to millions of Square sellers through their App Marketplace and even charge a nominal fee per order to cover the AWS bill; it would make it much easier to install and use; it would work cross-platform and not be limited to iOS devices only; it would run automatically in the background without any user interaction and would therefore require no additional training.

Having said that, using the built-in Shortcuts app and requiring user interaction is not necessarily a bad thing either: it makes sure that pickup times are scheduled more accurately thereby reducing the need to re-schedule deliveries; it ensures that a human being has visually checked the address and verified all delivery information entered by the customer, because you never know; but most importantly, by using the built-in shortcuts in iOS, it means that everything runs locally on the device without needing any order data to be sent to third-party servers, which is ideal for privacy.

Getting this to work was a lot harder than it should be though: reverse-engineering the Weebly JSON-RPC implementation on Square Online to get the order details in JSON format was a huge pain and very time consuming; I was pulling out my hair trying to set the values of <input> tags with React.js getting in the way on the DoorDash Drive Portal; and I don’t like that the copy and paste shortcuts have to be two separate actions and can’t just be one single shortcut.[5]

But at the end of the day, how it works doesn’t matter much to most restaurant owners, only the fact that it does work and that it saves a lot of time.

You can view the full contents of the shortcuts at any time within the Shortcuts app and it also appears in the video above, but for the sake of completeness, here’s a heavily-commented, self-documenting copy of the JavaScript portions:

Copy Delivery Info

// add a script tag to the document head to get access to ALL window objects
let script = document.createElement('script');
script.innerHTML = `
	// get the orderID, ownerID and siteID from the address bar
	let orderID	= window.location.hash.split('/').pop().toString();
	let ownerID	= window.location.pathname.split('/')[4];
	let siteID	= window.location.pathname.split('/')[6];

	// use Weebly/Square’s native commands to load the order information in JSON format
	window._W.Commerce.RPC.Order.read({"filter":[{"property":"owner_id","value":ownerID},{"property":"site_id","value":siteID},{"property":"site_order_id","value":orderID}],"limit":1,"single":true,"view":"detail","parse":true}).then(res => {
		// create a new script tag to store the order info JSON
		let jsonElement = document.createElement('script');
		jsonElement.setAttribute('type', 'application/json');
		jsonElement.setAttribute('id', 'DMorderData');
		jsonElement.innerHTML = JSON.stringify(res.data);
		document.head.appendChild(jsonElement);
	});
`;
document.head.appendChild(script);

// create a mutation observer to see when our data is added to the DOM
const obs = new MutationObserver((mutationsList, observer) => {
	for(const mutation of mutationsList) {
		let dataElement = document.querySelector('#DMorderData');

		// if/when the data element exists, parse the JSON and send it as output
		if (dataElement) {
			const rawData	= JSON.parse(dataElement.innerHTML);
			const dmOrder	= {
				orderID			: rawData.site_order_id,
				address			: `${rawData.shipments[0].street}, ${rawData.shipments[0].city}, ${rawData.shipments[0].region} ${rawData.shipments[0].postal_code}, ${rawData.shipments[0].country}`,
				suite			: rawData.shipments[0].street2,
				firstName		: rawData.original_customer[0].name_first,
				lastName		: rawData.original_customer[0].name_last,
				email			: rawData.shipments[0].email,
				phone			: rawData.shipments[0].phone,
				subTotal		: rawData.order_subtotal,
				itemCount		: rawData.items.length.toString(),
				tipAmount		: Math.round(rawData.order_tip_total * 100 / 2) / 100
			};

			// parse the order notes
			let orderNotes			= rawData.order_notes;
			let instructionsIndex	= orderNotes.indexOf('Delivery Instructions: ');
			dmOrder.instructions	= (instructionsIndex > 0)
									? orderNotes.substring(instructionsIndex + 23)
									: '';

			// console.log(dmOrder);
			completion(dmOrder);
			observer.disconnect();
		}
	}
});
obs.observe(document.querySelector('head'), { subtree : false, childList: true, attributes: false });

Paste Delivery Info

const dmOrder	= Dictionary;
const addInput	= document.querySelector('[data-test-id="guest-address-form"] input');

// see https://stackoverflow.com/questions/30683628/react-js-setting-value-of-input/52486921#52486921
function setNativeValue(element, value) {
	let lastValue = element.value;
	element.value = value;

	let event = new Event('input', { target: element, bubbles: true });
	// React 15
	event.simulated = true;
	// React 16
	let tracker = element._valueTracker;
	if (tracker) {
		tracker.setValue(lastValue);
	}
	element.dispatchEvent(event);
}

setNativeValue(addInput, dmOrder.address);
setNativeValue(document.querySelector('[name="dropoffAddressSubpremise"]'), dmOrder.suite);
setNativeValue(document.querySelector('[name="dropoffSpecialInstructions"]'), dmOrder.instructions);
setNativeValue(document.querySelector('[name="firstName"]'), dmOrder.firstName);
setNativeValue(document.querySelector('[name="lastName"]'), dmOrder.lastName);
setNativeValue(document.querySelector('[name="email"]'), dmOrder.email);
setNativeValue(document.querySelector('[type="tel"]'), dmOrder.phone);
setNativeValue(document.querySelector('[name="orderSize"]'), dmOrder.subTotal);
setNativeValue(document.querySelector('[name="driverTip"]'), dmOrder.tipAmount);
setNativeValue(document.querySelector('[name="driverReferenceTag"]'), dmOrder.orderID);
setNativeValue(document.querySelector('[name="numItems"]'), dmOrder.itemCount);
document.querySelector('#driveSubmit').click();
addInput.focus();

// Call completion to finish
completion(dmOrder);

Tip Amount Calculation

Since I like to think that most restaurants do the right thing and split tips 50/50 between the delivery driver and kitchen staff, the shortcut automatically calculates the driver tip to be half of the total tip received. If you need to, you can open the Shortcuts app to modify the “copy” shortcut and make any adjustments to this calculation to suit your needs:

tipAmount : Math.round(rawData.order_tip_total * 100 / 2) / 100
  • to give the delivery driver 100% of tips, remove / 2 from the calculation
  • to give the delivery driver 75% of tips, change / 2 to * 0.75
  • to give the delivery driver ⅔ of tips, change / 2 to / 3 * 2
  • etc.

Not For Profit

I don’t work for Square, DoorDash nor Frank’s Pizza House and have received no compensation for any of this. None. After creating this for Frank’s Pizza House, I realized that it could save many more restaurants a lot of time — and not just restaurants, but any kind of merchant that accepts delivery orders and uses both Square and DoorDash Drive — which is why I’ve decided to share this.

I always hope that my blog posts can be useful to people in some way or another and I never expect anything in return. If you want to use these free shortcuts, go ahead! The only thing I ask is, please don’t contact me asking for support or customizations.[6]

Terms of Use

These shortcuts have been tested with the current version of Apple’s iOS operating system and the Shortcuts app as of the date on this blog post. Should anything major change or break, this page might be updated from time to time. However, please keep in mind that these shortcuts depend on the DoorDash Drive Portal and on Square’s website, both of which are out of my control. I cannot and do not guarantee that these shortcuts will remain compatible with future updates to iOS or the Shortcuts app.

The shortcuts linked on this page are provided free of charge and as-is without any express or implied warranties including implied warranties of merchantability, fitness for a particular purpose, and non-infringement. I make no specific promises about the shortcuts, the specific functions of the shortcuts, or their reliability, availability, or ability to meet your needs. In addition, I will not be liable to you for any lost profits or other consequential, special, indirect, or incidental damages arising out of or in connection with your use of the shortcuts.

Additional References

For more information on iOS Shortcuts, check out the official Shortcuts User Guide on Apple.com. You may also find Federico Viticci’s shortcuts archive on MacStories to be useful.