What it does: Sends up to two emails to customers who abandon a cart, and skips the second email if they buy in the meantime. How it flows: 1. Webhook receives the cart data (email, name, cart_id, item). 2. Wait, then If checks the "purchased" value in the link. "true" stops the run, "false" continues. 3. Gmail sends the first reminder. 4. Wait1, then Get row(s) looks for the cart_id in the "purchases" data table. 5. If1 checks whether a row was found. A row means they bought, so the run stops. No row means the second email (with a discount) goes out. Fake store for testing: A second workflow (Webhook, then Insert row) writes a cart_id into the "purchases" table. Opening its link simulates a purchase. The two workflows share the data table, and the cart_id is what matches them. Key fixes along the way: - Browser links send GET requests, so data arrives under "query", not "body". - Turn on "Always Output Data" on the Get row(s) node, or the workflow stops when no row is found. - If1 must check {{ $json.cart_id }} with "is not empty", not the old "purchased" value. - Reference earlier data after Gmail/Wait nodes with $('Webhook').item.json.query.cart_id. - Test URLs (/webhook-test/) catch one request after clicking Execute workflow. Production URLs (/webhook/) need the workflow published. Still to do: - Connect a real store (POST payload instead of GET). - Replace the fake purchase table with a real order lookup. - Expose the webhook with a tunnel or hosted n8n. - Set real wait times (for example 1 hour and 24 hours). - Swap in the real cart link, discount code, and brand name.