Every morning, one email with yesterday's Shopify orders, sales and best sellers, and every tracked item running low or sold out.
Uses
GmailShopify
Start every day with your Shopify sales and stock
recipientEmail to blank.Set recipientEmail to blank.lowStockThreshold to 5.Set lowStockThreshold to 5.maxOrdersForTopProducts to 100.Set maxOrdersForTopProducts to 100.recipientEmail and save it as sendTo.Trim recipientEmail and save it as sendTo.sendTo doesn't contain @If sendTo doesn't contain @Yes
No
No steps
maxOrdersForTopProducts down and save it as orderCap.Round maxOrdersForTopProducts down and save it as orderCap.store to an empty record.Set store to an empty record.shopErrorIf a step below fails, save the error as shopErrorTry
store.Get your store. Save it as store.On error
shopError.message.Stop and report a problem: Lodol could not read your Shopify store, so no brief was sent. Check the Shopify connection under Integrations, then run this again. Shopify said: shopError.message.storeName to store.shop.name.Set storeName to store.shop.name.storeZone to store.shop.ianaTimezone.Set storeZone to store.shop.ianaTimezone.storeCurrency to store.shop.currencyCode.Set storeCurrency to store.shop.currencyCode.reportDay.Get yesterday's date and save it as reportDay.today.Get today's date and save it as today.reportDay and save it as dayName.Get the day of the week for reportDay and save it as dayName.reportDay readable as “Monday, November 2” and save it as dayLabel.Make reportDay readable as “Monday, November 2” and save it as dayLabel.reportDay readable as “2026-11-02T14:05:00Z” and save it as dayStart.Make reportDay readable as “2026-11-02T14:05:00Z” and save it as dayStart.today readable as “2026-11-02T14:05:00Z” and save it as dayEnd.Make today readable as “2026-11-02T14:05:00Z” and save it as dayEnd.dayStart readable as “2026-11-02” and save it as searchFrom.Make dayStart readable as “2026-11-02” and save it as searchFrom.dayEnd readable as “2026-11-02” and save it as searchTo.Make dayEnd readable as “2026-11-02” and save it as searchTo.reportDay and save it as weekBeforeDay.Get the date 7 days before reportDay and save it as weekBeforeDay.reportDay and save it as weekBeforeNextDay.Get the date 6 days before reportDay and save it as weekBeforeNextDay.weekBeforeDay readable as “2026-11-02T14:05:00Z” and save it as weekBeforeStart.Make weekBeforeDay readable as “2026-11-02T14:05:00Z” and save it as weekBeforeStart.weekBeforeNextDay readable as “2026-11-02T14:05:00Z” and save it as weekBeforeEnd.Make weekBeforeNextDay readable as “2026-11-02T14:05:00Z” and save it as weekBeforeEnd.weekBeforeStart readable as “2026-11-02” and save it as weekBeforeFrom.Make weekBeforeStart readable as “2026-11-02” and save it as weekBeforeFrom.weekBeforeEnd readable as “2026-11-02” and save it as weekBeforeTo.Make weekBeforeEnd readable as “2026-11-02” and save it as weekBeforeTo.dayOrders to an empty list.Set dayOrders to an empty list.orderCursor to blank.Set orderCursor to blank.moreOrderPages to true.Set moreOrderPages to true.moreOrderPages is yes:While moreOrderPages is yes:orderPage to an empty record.Set orderPage to an empty record.ordersErrorIf a step below fails, save the error as ordersErrorTry
orderPage.List orders. Save it as orderPage.On error
ordersError.message.Stop and report a problem: Lodol could not read yesterday's orders from Shopify, so no brief was sent. Shopify said: ordersError.message.orderPage.orders where item.createdAt is greater than or equal to dayStart and item.createdAt is… and save it as pageOrders.Keep each item in orderPage.orders where item.createdAt is greater than or equal to dayStart and item.createdAt is… and save it as pageOrders.dayOrders and pageOrders into one list and save it as dayOrders.Combine dayOrders and pageOrders into one list and save it as dayOrders.orderCursor to orderPage.next_cursor.Change orderCursor to orderPage.next_cursor.moreOrderPages to orderPage.has_more.Change moreOrderPages to orderPage.has_more.orderPage.orders[-1].createdAt is greater than or equal to dayEndIf orderPage.orders[-1].createdAt is greater than or equal to dayEndYes
moreOrderPages to false.Change moreOrderPages to false.No
No steps
dayOrders and save it as orderCount.Count the items in dayOrders and save it as orderCount.totalPriceSet.shopMoney.amount from every item in dayOrders and save it as orderTotals.Get totalPriceSet.shopMoney.amount from every item in dayOrders and save it as orderTotals.orderTotals and save it as grossSales.Add up orderTotals and save it as grossSales.totalRefundedSet.shopMoney.amount from every item in dayOrders and save it as orderRefunds.Get totalRefundedSet.shopMoney.amount from every item in dayOrders and save it as orderRefunds.orderRefunds and save it as refundedSales.Add up orderRefunds and save it as refundedSales.netSales to grossSales minus refundedSales.Set netSales to grossSales minus refundedSales.weekBeforeOrders to an empty list.Set weekBeforeOrders to an empty list.weekBeforeCursor to blank.Set weekBeforeCursor to blank.moreWeekBeforePages to true.Set moreWeekBeforePages to true.moreWeekBeforePages is yes:While moreWeekBeforePages is yes:weekBeforePage to an empty record.Set weekBeforePage to an empty record.weekBeforeErrorIf a step below fails, save the error as weekBeforeErrorTry
weekBeforePage.List orders. Save it as weekBeforePage.On error
weekBeforeError.message.Stop and report a problem: Lodol could not read last week's orders from Shopify for the comparison, so no brief was sent. Shopify said: weekBeforeError.message.weekBeforePage.orders where item.createdAt is greater than or equal to weekBeforeStart and item.createdAt… and save it as weekBeforeMatches.Keep each item in weekBeforePage.orders where item.createdAt is greater than or equal to weekBeforeStart and item.createdAt… and save it as weekBeforeMatches.weekBeforeOrders and weekBeforeMatches into one list and save it as weekBeforeOrders.Combine weekBeforeOrders and weekBeforeMatches into one list and save it as weekBeforeOrders.weekBeforeCursor to weekBeforePage.next_cursor.Change weekBeforeCursor to weekBeforePage.next_cursor.moreWeekBeforePages to weekBeforePage.has_more.Change moreWeekBeforePages to weekBeforePage.has_more.weekBeforePage.orders[-1].createdAt is greater than or equal to weekBeforeEndIf weekBeforePage.orders[-1].createdAt is greater than or equal to weekBeforeEndYes
moreWeekBeforePages to false.Change moreWeekBeforePages to false.No
No steps
weekBeforeOrders and save it as weekBeforeCount.Count the items in weekBeforeOrders and save it as weekBeforeCount.totalPriceSet.shopMoney.amount from every item in weekBeforeOrders and save it as weekBeforeTotals.Get totalPriceSet.shopMoney.amount from every item in weekBeforeOrders and save it as weekBeforeTotals.weekBeforeTotals and save it as weekBeforeGross.Add up weekBeforeTotals and save it as weekBeforeGross.totalRefundedSet.shopMoney.amount from every item in weekBeforeOrders and save it as weekBeforeRefunds.Get totalRefundedSet.shopMoney.amount from every item in weekBeforeOrders and save it as weekBeforeRefunds.weekBeforeRefunds and save it as weekBeforeRefunded.Add up weekBeforeRefunds and save it as weekBeforeRefunded.weekBeforeSales to weekBeforeGross minus weekBeforeRefunded.Set weekBeforeSales to weekBeforeGross minus weekBeforeRefunded.netSales to 2 decimal places and save it as salesRounded.Round netSales to 2 decimal places and save it as salesRounded.salesRounded as a currency and save it as salesText.Format salesRounded as a currency and save it as salesText.weekBeforeSales to 2 decimal places and save it as weekBeforeRounded.Round weekBeforeSales to 2 decimal places and save it as weekBeforeRounded.weekBeforeRounded as a currency and save it as weekBeforeSalesText.Format weekBeforeRounded as a currency and save it as weekBeforeSalesText.averageOrder to 0.Set averageOrder to 0.orderCount is greater than 0If orderCount is greater than 0Yes
averageOrder to netSales divided by orderCount.Change averageOrder to netSales divided by orderCount.No
No steps
averageOrder to 2 decimal places and save it as averageRounded.Round averageOrder to 2 decimal places and save it as averageRounded.averageRounded as a currency and save it as averageText.Format averageRounded as a currency and save it as averageText.orderWord to orders.Set orderWord to orders.orderCount is 1If orderCount is 1Yes
orderWord to order.Change orderWord to order.No
No steps
weekBeforeOrderWord to orders.Set weekBeforeOrderWord to orders.weekBeforeCount is 1If weekBeforeCount is 1Yes
weekBeforeOrderWord to order.Change weekBeforeOrderWord to order.No
No steps
the same as the @dayName before and save it as ordersComparison.Build the text the same as the @dayName before and save it as ordersComparison.orderCount is greater than weekBeforeCountIf orderCount is greater than weekBeforeCountYes
up from @weekBeforeCount the @dayName before and save it as ordersComparison.Build the text up from @weekBeforeCount the @dayName before and save it as ordersComparison.Else if @orderCount is less than @weekBeforeCount
down from @weekBeforeCount the @dayName before and save it as ordersComparison.Build the text down from @weekBeforeCount the @dayName before and save it as ordersComparison.Otherwise
No steps
the same as the @dayName before and save it as salesComparison.Build the text the same as the @dayName before and save it as salesComparison.weekBeforeRounded is less than or equal to 0If weekBeforeRounded is less than or equal to 0Yes
with no sales the @dayName before and save it as salesComparison.Build the text with no sales the @dayName before and save it as salesComparison.Else if @salesRounded is not @weekBeforeRounded
salesChange to salesRounded minus weekBeforeRounded.Set salesChange to salesRounded minus weekBeforeRounded.salesChange and save it as salesSwing.Calculate the absolute value of salesChange and save it as salesSwing.swingShare to salesSwing divided by weekBeforeRounded.Set swingShare to salesSwing divided by weekBeforeRounded.swingShare as a percentage with 0 decimal places and save it as swingPercent.Format swingShare as a percentage with 0 decimal places and save it as swingPercent.salesDirection to up.Set salesDirection to up.salesChange is less than 0If salesChange is less than 0Yes
salesDirection to down.Change salesDirection to down.No
No steps
@salesDirection @swingPercent from @weekBeforeSalesText the @dayName before and save it as salesComparison.Build the text @salesDirection @swingPercent from @weekBeforeSalesText the @dayName before and save it as salesComparison.Otherwise
No steps
Orders: @orderCount, @ordersComparison Sales: @salesText, @salesComparison Average order: @averageText and save it as salesSection.Build the text Orders: @orderCount, @ordersComparison Sales: @salesText, @salesComparison Average order: @averageText and save it as salesSection.orderCount is 0 and weekBeforeCount is 0If orderCount is 0 and weekBeforeCount is 0Yes
No orders yesterday, and none the @dayName before either. and save it as salesSection.Build the text No orders yesterday, and none the @dayName before either. and save it as salesSection.Else if @orderCount is 0
No orders yesterday. The @dayName before had @weekBeforeCount @weekBeforeOrderWord and @weekBeforeSalesText in sales. and save it as salesSection.Build the text No orders yesterday. The @dayName before had @weekBeforeCount @weekBeforeOrderWord and @weekBeforeSalesText in sales. and save it as salesSection.Otherwise
No steps
orderCap items of dayOrders and save it as ordersToRank.Take the first orderCap items of dayOrders and save it as ordersToRank.soldItems to an empty list.Set soldItems to an empty list.unreadOrders to an empty list.Set unreadOrders to an empty list.lastOrderError to blank.Set lastOrderError to blank.order in ordersToRank:For each order in ordersToRank:orderErrorIf a step below fails, save the error as orderErrorTry
order. Save it as orderDetail.Get order. Save it as orderDetail.soldItems and orderDetail.order.lineItems.nodes into one list and save it as soldItems.Combine soldItems and orderDetail.order.lineItems.nodes into one list and save it as soldItems.On error
order.name to the end of unreadOrders and save it as unreadOrders.Add order.name to the end of unreadOrders and save it as unreadOrders.lastOrderError to orderError.message.Change lastOrderError to orderError.message.soldItems by title, with the total quantity of each and save it as productUnits.Group the items in soldItems by title, with the total quantity of each and save it as productUnits.productUnits by total, largest first and save it as rankedProducts.Sort productUnits by total, largest first and save it as rankedProducts.rankedProducts and save it as topProducts.Take the first 5 items of rankedProducts and save it as topProducts.topProductLines to an empty list.Set topProductLines to an empty list.rank to 0.Set rank to 0.product in topProducts:For each product in topProducts:rank.Add 1 to rank.unitWord to units.Set unitWord to units.product.total is 1If product.total is 1Yes
unitWord to unit.Change unitWord to unit.No
No steps
rank. product.key: product.total unitWord to the end of topProductLines and save it as topProductLines.Add rank. product.key: product.total unitWord to the end of topProductLines and save it as topProductLines.topProductLines with a new line and save it as productsSection.Join topProductLines with a new line and save it as productsSection.orderCount is 0If orderCount is 0Yes
productsSection to No orders, so nothing to rank..Change productsSection to No orders, so nothing to rank..Else if @topProducts is empty
productsSection to None of yesterday's orders could be read, so there is no ranking today..Change productsSection to None of yesterday's orders could be read, so there is no ranking today..Otherwise
No steps
rankingNote to blank.Set rankingNote to blank.orderCount is greater than orderCapIf orderCount is greater than orderCapYes
(Counted from the first @orderCap of yesterday's @orderCount orders. Raise 'maxOrdersForTopProducts' to count more.) and save it as rankingNote.Build the text (Counted from the first @orderCap of yesterday's @orderCount orders. Raise 'maxOrdersForTopProducts' to count more.) and save it as rankingNote.No
No steps
unreadOrders and save it as unreadCount.Count the items in unreadOrders and save it as unreadCount.unreadOrders and save it as unreadShown.Take the first 10 items of unreadOrders and save it as unreadShown.unreadShown with , and save it as unreadList.Join unreadShown with , and save it as unreadList.unreadVerb to are.Set unreadVerb to are.unreadCount is 1If unreadCount is 1Yes
unreadVerb to is.Change unreadVerb to is.No
No steps
unreadMore to blank.Set unreadMore to blank.unreadCount is greater than 10If unreadCount is greater than 10Yes
and , unreadCount minus 10, more] with nothing and save it as unreadMore.Join [ and , unreadCount minus 10, more] with nothing and save it as unreadMore.No
No steps
unreadNote to blank.Set unreadNote to blank.unreadCount is greater than 0If unreadCount is greater than 0Yes
(@unreadCount of yesterday's orders could not be read from Shopify and @unreadVerb left out of this ranking: @unreadList@unreadMore.) and save it as unreadNote.Build the text (@unreadCount of yesterday's orders could not be read from Shopify and @unreadVerb left out of this ranking: @unreadList@unreadMore.) and save it as unreadNote.No
No steps
lowStockItems to an empty list.Set lowStockItems to an empty list.noStockFigure to an empty list.Set noStockFigure to an empty list.stockFigures to an empty list.Set stockFigures to an empty list.variantsChecked to 0.Set variantsChecked to 0.trackedCount to 0.Set trackedCount to 0.variantCursor to blank.Set variantCursor to blank.moreVariantPages to true.Set moreVariantPages to true.moreVariantPages is yes:While moreVariantPages is yes:variantPage to an empty record.Set variantPage to an empty record.stockErrorIf a step below fails, save the error as stockErrorTry
variantPage.List product variants. Save it as variantPage.On error
stockError.message.Stop and report a problem: Lodol could not read your stock levels from Shopify, so no brief was sent. Shopify said: stockError.message.variantPage.variants where item.inventoryItem.tracked is yes and save it as pageTracked.Keep each item in variantPage.variants where item.inventoryItem.tracked is yes and save it as pageTracked.pageTracked where item.product.status is not DRAFT and item.product.status is not ARCHIVED… and save it as pageLowStock.Keep each item in pageTracked where item.product.status is not DRAFT and item.product.status is not ARCHIVED… and save it as pageLowStock.variantPage.variants where item.inventoryItem is empty or item.inventoryItem.tracked is yes and… and save it as pageNoStockFigure.Keep each item in variantPage.variants where item.inventoryItem is empty or item.inventoryItem.tracked is yes and… and save it as pageNoStockFigure.lowStockItems and pageLowStock into one list and save it as lowStockItems.Combine lowStockItems and pageLowStock into one list and save it as lowStockItems.noStockFigure and pageNoStockFigure into one list and save it as noStockFigure.Combine noStockFigure and pageNoStockFigure into one list and save it as noStockFigure.pageTracked where item.inventoryQuantity isn't empty and save it as pageStockFigures.Keep each item in pageTracked where item.inventoryQuantity isn't empty and save it as pageStockFigures.stockFigures and pageStockFigures into one list and save it as stockFigures.Combine stockFigures and pageStockFigures into one list and save it as stockFigures.variantsChecked to variantsChecked plus variantPage.count.Change variantsChecked to variantsChecked plus variantPage.count.pageTracked and save it as pageTrackedCount.Count the items in pageTracked and save it as pageTrackedCount.trackedCount to trackedCount plus pageTrackedCount.Change trackedCount to trackedCount plus pageTrackedCount.variantCursor to variantPage.next_cursor.Change variantCursor to variantPage.next_cursor.moreVariantPages to variantPage.has_more.Change moreVariantPages to variantPage.has_more.noStockFigure and save it as noStockFigureCount.Count the items in noStockFigure and save it as noStockFigureCount.noStockFigureCount is greater than 0 and stockFigures is emptyIf noStockFigureCount is greater than 0 and stockFigures is emptyYes
No
No steps
lowStockItems by inventoryQuantity, smallest first and save it as sortedLowStock.Sort lowStockItems by inventoryQuantity, smallest first and save it as sortedLowStock.lowStockItems where item.inventoryQuantity is less than or equal to 0 and save it as outOfStock.Keep each item in lowStockItems where item.inventoryQuantity is less than or equal to 0 and save it as outOfStock.outOfStock and save it as outCount.Count the items in outOfStock and save it as outCount.lowStockItems and save it as lowStockCount.Count the items in lowStockItems and save it as lowStockCount.runningLowCount to lowStockCount minus outCount.Set runningLowCount to lowStockCount minus outCount.sortedLowStock and save it as stockShown.Take the first 40 items of sortedLowStock and save it as stockShown.stockLines to an empty list.Set stockLines to an empty list.variant in stockShown:For each variant in stockShown:itemName to variant.product.title.Set itemName to variant.product.title.variant.title is not Default TitleIf variant.title is not Default TitleYes
@variant.product.title - @variant.title and save it as itemName.Build the text @variant.product.title - @variant.title and save it as itemName.No
No steps
skuNote to blank.Set skuNote to blank.variant.sku isn't emptyIf variant.sku isn't emptyYes
(SKU @variant.sku) and save it as skuNote.Build the text (SKU @variant.sku) and save it as skuNote.No
No steps
@variant.inventoryQuantity left and save it as stockNow.Build the text @variant.inventoryQuantity left and save it as stockNow.variant.inventoryQuantity is less than 0If variant.inventoryQuantity is less than 0Yes
variant.inventoryQuantity and save it as oversoldBy.Calculate the absolute value of variant.inventoryQuantity and save it as oversoldBy.out of stock, oversold by @oversoldBy and save it as stockNow.Build the text out of stock, oversold by @oversoldBy and save it as stockNow.Else if @variant.inventoryQuantity is 0
stockNow to out of stock.Change stockNow to out of stock.Otherwise
No steps
itemName@skuNote: stockNow to the end of stockLines and save it as stockLines.Add • itemName@skuNote: stockNow to the end of stockLines and save it as stockLines.stockLines with a new line and save it as stockList.Join stockLines with a new line and save it as stockList.stockNotShown to lowStockCount minus 40.Set stockNotShown to lowStockCount minus 40.moreStockNote to blank.Set moreStockNote to blank.stockNotShown is greater than 0If stockNotShown is greater than 0Yes
...and @stockNotShown more. Products > Inventory in Shopify lists them all. and save it as moreStockNote.Build the text ...and @stockNotShown more. Products > Inventory in Shopify lists them all. and save it as moreStockNote.No
No steps
noStockFigureNote to blank.Set noStockFigureNote to blank.noStockFigureCount is greater than 0If noStockFigureCount is greater than 0Yes
(Shopify gave no stock figure for @noStockFigureCount of your items, so they were not checked.) and save it as noStockFigureNote.Build the text (Shopify gave no stock figure for @noStockFigureCount of your items, so they were not checked.) and save it as noStockFigureNote.No
No steps
itemWord to items.Set itemWord to items.lowStockCount is 1If lowStockCount is 1Yes
itemWord to item.Change itemWord to item.No
No steps
@lowStockCount @itemWord, @outCount of them out of stock and save it as stockSummary.Build the text @lowStockCount @itemWord, @outCount of them out of stock and save it as stockSummary.outCount is 0If outCount is 0Yes
@lowStockCount @itemWord running low and save it as stockSummary.Build the text @lowStockCount @itemWord running low and save it as stockSummary.Else if @outCount is @lowStockCount
@lowStockCount @itemWord, all out of stock and save it as stockSummary.Build the text @lowStockCount @itemWord, all out of stock and save it as stockSummary.lowStockCount is 1If lowStockCount is 1Yes
stockSummary to 1 item, out of stock.Change stockSummary to 1 item, out of stock.No
No steps
Otherwise
No steps
@stockSummary: @stockList@moreStockNote@noStockFigureNote and save it as stockSection.Build the text @stockSummary: @stockList@moreStockNote@noStockFigureNote and save it as stockSection.variantsChecked is 0If variantsChecked is 0Yes
stockSection to Your store has no products yet, so there is no stock to check..Change stockSection to Your store has no products yet, so there is no stock to check..Else if @trackedCount is 0
None of your products has 'Track quantity' turned on in Shopify, so there is no stock to check. Turn it on for a product to include it here.@noStockFigureNote and save it as stockSection.Build the text None of your products has 'Track quantity' turned on in Shopify, so there is no stock to check. Turn it on for a product to include it here.@noStockFigureNote and save it as stockSection.Else if @lowStockCount is 0
Every tracked item has more than @lowStockThreshold units in stock.@noStockFigureNote and save it as stockSection.Build the text Every tracked item has more than @lowStockThreshold units in stock.@noStockFigureNote and save it as stockSection.Otherwise
No steps
@orderCount @orderWord, @salesText in sales and save it as salesHeadline.Build the text @orderCount @orderWord, @salesText in sales and save it as salesHeadline.orderCount is 0If orderCount is 0Yes
salesHeadline to no orders.Change salesHeadline to no orders.No
No steps
stockHeadline to blank.Set stockHeadline to blank.outCount is greater than 0If outCount is greater than 0Yes
, @outCount out of stock and save it as stockHeadline.Build the text , @outCount out of stock and save it as stockHeadline.Else if @runningLowCount is greater than 0
, @runningLowCount running low and save it as stockHeadline.Build the text , @runningLowCount running low and save it as stockHeadline.Otherwise
No steps
sendErrorIf a step below fails, save the error as sendErrorTry
sendTo. Save it as sent.Send an email to sendTo. Save it as sent.
Subject: dayName at storeName: salesHeadline@stockHeadlineGood morning,
Here is how storeName did yesterday, dayLabel.
SALES
salesSection
TOP 5 PRODUCTS BY UNITS ORDERED
...On error
sendError.message.Stop and report a problem: The brief could not be sent from Gmail, so nobody received it. Check the Gmail connection under Integrations, then run this again. Gmail said: sendError.message.unreadCount is greater than 0If unreadCount is greater than 0Yes
sendTo, but unreadCount of yesterday's orders could not be read from Shopify and unreadVerb left out of the top products: unreadList@unreadMore. Shopify said: lastOrderError.Stop and report a problem: Sent the brief to sendTo, but unreadCount of yesterday's orders could not be read from Shopify and unreadVerb left out of the top products: unreadList@unreadMore. Shopify said: lastOrderError.No
No steps
dayLabel to sendTo: salesHeadline, outCount out of stock and runningLowCount running low.Finish the run: Sent the brief for dayLabel to sendTo: salesHeadline, outCount out of stock and runningLowCount running low.