← Back to Dimensions

Delivery Attempt Number

Also known as: Attempt Number, Delivery Attempt Sequence, delivery_attempt_number

OperationsdimensionE-commerce: Post-Purchase Logistics & FulfillmentE-commerce

Ordinal of the carrier delivery attempt on a shipment: 1, 2, 3 or 4+, read from attempted and delivered scans. Splits delivery outcomes into first-attempt success versus redelivery.

Business Use Case

1️⃣ Operations: when one carrier's share of attempt 2+ rises, raises it at the carrier review with lane-level evidence. 2️⃣ Customer Service: when a shipment reaches attempt 2, sends a reschedule or pickup-point option before attempt 3. 3️⃣ Finance: at month end, reconciles carrier redelivery surcharges against shipments with attempt 2 or higher.

Business Criticality

Medium

Journey / Navigation Area

Generic

Owning Function

Operations

Scope

Event

Calculation Notes

1️⃣ Source: derived from carrier tracking scans per tracking number in the OMS backend, not sent in a data layer. 2️⃣ Counting: each out-for-delivery run ending in an attempted or delivered scan is one attempt; the first is 1, each later one adds 1. 3️⃣ Values: the string 1, 2, 3 or 4+, as in Number of Shipments. A shipment with no attempt scan yet is (not set), never 0. 4️⃣ Shipment scope: one value per tracking number. A split order carries one value per shipment, never one per order. 5️⃣ Exclusions: store pickup and ship-to-store orders have no home delivery attempt and stay (not set). 6️⃣ Final value: frozen at the delivered, redirected-to-pickup-point or returned-to-sender scan; open shipments show the latest attempt so far. 7️⃣ Dedupe: repeated attempted scans for one tracking number on the same local day count as one attempt.

Technical Details

Data Typestring
Lookback WindowDaily, Weekly, Monthly

Events

SQL Queries

Google Analytics 4 (BigQuery)
-- ==========================================
-- 1. GOOGLE BIGQUERY SQL
-- ==========================================
-- Backend source: OMS shipment tracking scans, not GA4 export tables
-- Relative reporting window: last 90 complete days
DECLARE start_date DATE DEFAULT DATE_SUB(CURRENT_DATE(), INTERVAL 90 DAY);
DECLARE end_date DATE DEFAULT DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY);

-- Shipments with any scan in the window, every fulfillment method kept (including NULL)
WITH shipments AS (
  SELECT DISTINCT s.tracking_number, s.fulfillment_method
  FROM `your-project.oms.shipments` AS s
  JOIN `your-project.oms.shipment_tracking_scans` AS sc ON sc.tracking_number = s.tracking_number
  WHERE sc.scan_local_date BETWEEN start_date AND end_date
),

-- First terminal scan per shipment, where the value freezes
terminal AS (
  SELECT tracking_number, scan_timestamp AS terminal_ts, scan_id AS terminal_scan_id
  FROM (
    SELECT
      sc.tracking_number, sc.scan_timestamp, sc.scan_id,
      ROW_NUMBER() OVER (PARTITION BY sc.tracking_number ORDER BY sc.scan_timestamp, sc.scan_id) AS terminal_rank
    FROM `your-project.oms.shipment_tracking_scans` AS sc
    JOIN shipments USING (tracking_number)
    WHERE sc.scan_type IN ('DELIVERED', 'REDIRECTED_TO_PICKUP_POINT', 'RETURNED_TO_SENDER')
      AND sc.scan_local_date <= end_date
  )
  WHERE terminal_rank = 1
),

-- Relevant scans at or before the first terminal scan; repeated attempted scans on the same local day count once
scans AS (
  SELECT tracking_number, scan_type, scan_timestamp, scan_id
  FROM (
    SELECT
      sc.tracking_number, sc.scan_type, sc.scan_timestamp, sc.scan_id,
      ROW_NUMBER() OVER (PARTITION BY sc.tracking_number, sc.scan_type, sc.scan_local_date ORDER BY sc.scan_timestamp, sc.scan_id) AS same_day_rank
    FROM `your-project.oms.shipment_tracking_scans` AS sc
    JOIN shipments AS sh ON sh.tracking_number = sc.tracking_number
    LEFT JOIN terminal AS t ON t.tracking_number = sc.tracking_number
    WHERE sc.scan_type IN ('OUT_FOR_DELIVERY', 'DELIVERY_ATTEMPTED', 'DELIVERED')
      AND sc.scan_local_date <= end_date
      AND (t.terminal_ts IS NULL
        OR sc.scan_timestamp < t.terminal_ts
        OR (sc.scan_timestamp = t.terminal_ts AND sc.scan_id <= t.terminal_scan_id))
  )
  WHERE scan_type <> 'DELIVERY_ATTEMPTED' OR same_day_rank = 1
),

-- An attempt is an attempted or delivered scan that follows an out-for-delivery scan
ordered AS (
  SELECT
    tracking_number, scan_type,
    LAG(scan_type) OVER (PARTITION BY tracking_number ORDER BY scan_timestamp, scan_id) AS prev_scan_type
  FROM scans
),
attempts AS (
  SELECT tracking_number, COUNT(*) AS attempt_number
  FROM ordered
  WHERE scan_type IN ('DELIVERY_ATTEMPTED', 'DELIVERED')
    AND prev_scan_type = 'OUT_FOR_DELIVERY'
  GROUP BY tracking_number
)

-- Per-shipment value: 1, 2, 3 or 4+; store pickup, ship-to-store and no attempt yet are (not set)
SELECT
  s.tracking_number,
  CASE
    WHEN s.fulfillment_method IN ('store_pickup', 'ship_to_store') THEN '(not set)'
    WHEN a.attempt_number IS NULL THEN '(not set)'
    WHEN a.attempt_number >= 4 THEN '4+'
    ELSE CAST(a.attempt_number AS STRING)
  END AS delivery_attempt_number
FROM shipments AS s
LEFT JOIN attempts AS a ON a.tracking_number = s.tracking_number;
Adobe Experience Platform (AEP Query Service)
-- ==========================================
-- 2. ADOBE AEP QUERY SERVICE SQL
-- ==========================================
-- Backend source: OMS shipment tracking scans, not web event datasets
-- Relative reporting window: last 90 complete days
WITH params AS (
  SELECT date_sub(current_date(), 90) AS start_date,
         date_sub(current_date(), 1) AS end_date
),

-- Shipments with any scan in the window, every fulfillment method kept (including NULL)
shipments AS (
  SELECT DISTINCT s.tracking_number, s.fulfillment_method
  FROM oms_shipments s
  JOIN oms_shipment_tracking_scans sc ON sc.tracking_number = s.tracking_number
  CROSS JOIN params p
  WHERE sc.scan_local_date BETWEEN p.start_date AND p.end_date
),

-- First terminal scan per shipment, where the value freezes
terminal AS (
  SELECT tracking_number, scan_timestamp AS terminal_ts, scan_id AS terminal_scan_id
  FROM (
    SELECT
      sc.tracking_number, sc.scan_timestamp, sc.scan_id,
      ROW_NUMBER() OVER (PARTITION BY sc.tracking_number ORDER BY sc.scan_timestamp, sc.scan_id) AS terminal_rank
    FROM oms_shipment_tracking_scans sc
    JOIN shipments sh ON sh.tracking_number = sc.tracking_number
    CROSS JOIN params p
    WHERE sc.scan_type IN ('DELIVERED', 'REDIRECTED_TO_PICKUP_POINT', 'RETURNED_TO_SENDER')
      AND sc.scan_local_date <= p.end_date
  ) r
  WHERE terminal_rank = 1
),

-- Relevant scans at or before the first terminal scan; repeated attempted scans on the same local day count once
scans AS (
  SELECT tracking_number, scan_type, scan_timestamp, scan_id
  FROM (
    SELECT
      sc.tracking_number, sc.scan_type, sc.scan_timestamp, sc.scan_id,
      ROW_NUMBER() OVER (PARTITION BY sc.tracking_number, sc.scan_type, sc.scan_local_date ORDER BY sc.scan_timestamp, sc.scan_id) AS same_day_rank
    FROM oms_shipment_tracking_scans sc
    JOIN shipments sh ON sh.tracking_number = sc.tracking_number
    LEFT JOIN terminal t ON t.tracking_number = sc.tracking_number
    CROSS JOIN params p
    WHERE sc.scan_type IN ('OUT_FOR_DELIVERY', 'DELIVERY_ATTEMPTED', 'DELIVERED')
      AND sc.scan_local_date <= p.end_date
      AND (t.terminal_ts IS NULL
        OR sc.scan_timestamp < t.terminal_ts
        OR (sc.scan_timestamp = t.terminal_ts AND sc.scan_id <= t.terminal_scan_id))
  ) d
  WHERE scan_type <> 'DELIVERY_ATTEMPTED' OR same_day_rank = 1
),

-- An attempt is an attempted or delivered scan that follows an out-for-delivery scan
ordered AS (
  SELECT
    tracking_number, scan_type,
    LAG(scan_type) OVER (PARTITION BY tracking_number ORDER BY scan_timestamp, scan_id) AS prev_scan_type
  FROM scans
),
attempts AS (
  SELECT tracking_number, COUNT(*) AS attempt_number
  FROM ordered
  WHERE scan_type IN ('DELIVERY_ATTEMPTED', 'DELIVERED')
    AND prev_scan_type = 'OUT_FOR_DELIVERY'
  GROUP BY tracking_number
)

-- Per-shipment value: 1, 2, 3 or 4+; store pickup, ship-to-store and no attempt yet are (not set)
SELECT
  s.tracking_number,
  CASE
    WHEN s.fulfillment_method IN ('store_pickup', 'ship_to_store') THEN '(not set)'
    WHEN a.attempt_number IS NULL THEN '(not set)'
    WHEN a.attempt_number >= 4 THEN '4+'
    ELSE CAST(a.attempt_number AS STRING)
  END AS delivery_attempt_number
FROM shipments s
LEFT JOIN attempts a ON a.tracking_number = s.tracking_number;

Source Data

ERP

Dependencies

Prerequisite: List the dependencies required for this Dimension

Dimensions:

Report Attributes

carrier delivery-region shipping-tier delivery-exception-type delivery-time-window

Segment Eligibility

true

Governance

Data SensitivityInternal

Governance

Created bydevyendarm
Created on10/11/2026
Last modified bydevyendarm
Last modified on10/11/2026
StatusPUBLISHED

GitHub

View related Pull Requestcatalog/dimensions/delivery-attempt-number.yml

Community Discussion