Usually you would look to do this with help from your Shopping Cart. I know for Shopify they can tie into Marketo to assist with an abandoned cart campaign. Who is your Shopping Cart vendor and the Community may be able to offer some alternatives for you.
We don't have a specific vendor as the website is built with a custom "CMS", so everything is done in house.
The data is being send over perfectly to the custom object but as each item is an individual object it is trigger an email for each object created. We need a way for it to trigger on new custom objects but wait X minutes and only send 1 email.
In the current design, the intended object (the basket) doesn't actually exist.
In fact, even if you could trigger every hour (which you could do via an external cron job) this still wouldn't fix the problem, because the job may run when not all item objects have been created. Also, batches will eventually overflow the 10-historical-item limit. You really want to work with triggers here.
You need to rethink the design so the basket itself is a CO. Pass the items as nested JSON objects inside the Basket CO, or as linked Item COs.
The problem with one basket being a custom object is it is no longer dynamic (unless there is a way). If we say added:
item 1 title
item 1 price
item 2 title
item 2 price
There would only be custom object fields for those two items, so if someone has three items in their basket then they won't see it in the email.
If there is a way of making the custom object more dynamic that would be great. We'd want a way to store all the items without us knowing exactly how many as it will differ on the customer.
I think you need to read my answer more carefully.
You can create a Basket CO that links to more than one Item CO. This would be a more proper object model.
Or (I would probably do it this way for simplicity) have a Basket CO with a (single) text field ItemsJSON. This field holds a dynamic JSON array of all the items in a basket, not a fixed count (up to 32K of information, which is a ton of data for a single basket!). You can read ItemsJSON from Velocity.