← Back to Dimensions

Delivery Exception Type

Also known as: Shipment Exception Reason, Carrier Exception Type, Delivery Exception Reason

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

Carrier-reported reason a shipment stalled or failed in transit: weather, address issue, damaged, recipient unavailable, held at facility. Used to split failed deliveries by root cause.

Business Use Case

1️⃣ Customer Service: on a damaged or address-issue exception, contact the customer before the WISMO call arrives.,2️⃣ Logistics: when one carrier's facility-hold or weather share spikes, shift volume to the backup carrier.,3️⃣ Product: when address-issue exceptions rise, tighten address validation at the shipping step of checkout.,4️⃣ Finance: file damage and loss claims against carrier SLA credits using damaged-exception packages.

Business Criticality

High

Journey / Navigation Area

Generic

Owning Function

Customer Service

Scope

Event

Calculation Notes

1️⃣ Map raw carrier codes (UPS, FedEx, USPS, DHL) to one fixed value list; unmapped codes go to 'other', never passed through raw.,2️⃣ Grain is the package (tracking number), not the order; a split shipment can carry a different exception type per package.,3️⃣ Each exception scan keeps its own value; for package-level reporting use the last exception before delivery or return to sender.,4️⃣ Attempted delivery with a notice left maps to recipient unavailable; customer-requested holds and reroutes are not exceptions.,5️⃣ Null when a package has no exception; filter on null for clean deliveries rather than storing a 'none' value.,6️⃣ Date by the carrier exception scan timestamp converted to UTC, not by order or ship date.,7️⃣ Values seen on tracking pages are reconciled to OMS carrier events; the OMS value wins on conflict.

Technical Details

Data Typestring
Lookback WindowEvent, Daily, Weekly, Monthly

Events

PlatformEvent
Google Analytics 4page_view
AdobepageView

Data Mappings

W3 Data Layer
{
  "event": [
    {
      "page": {
        "pageInfo": {
          "pageName": "Order Status",
          "pageType": "order_status"
        }
      },
      "shipment": {
        "orderID": "",
        "trackingNumber": "",
        "carrier": "",
        "deliveryExceptionType": "",
        "exceptionTimestamp": "",
        "shipmentMode": "",
        "fulfillmentMethod": "",
        "deliveryRegion": "",
        "shippingTier": ""
      }
    }
  ]
}
GA4 Data Layer
{
  "event": "page_view",
  "page_type": "order_status",
  "order_id": "ORD-100234",
  "carrier": "UPS",
  "tracking_number": "1Z999AA10123456784",
  "delivery_exception_type": "address_issue",
  "exception_timestamp": "2026-09-23T14:12:00Z",
  "shipment_mode": "Standard",
  "fulfillment_method": "ship_to_home",
  "delivery_region": "US-West",
  "shipping_tier": "Standard"
}
Adobe Client Data Layer
{
  "event": "pageView",
  "page": {
    "pageType": "order_status"
  },
  "shipment": {
    "orderId": "ORD-100234",
    "carrier": "UPS",
    "trackingNumber": "1Z999AA10123456784",
    "deliveryExceptionType": "address_issue",
    "exceptionTimestamp": "2026-09-23T14:12:00Z",
    "shipmentMode": "Standard",
    "fulfillmentMethod": "ship_to_home",
    "deliveryRegion": "US-West",
    "shippingTier": "Standard"
  }
}
XDM Mapping
{
  "eventType": "pageView",
  "page": {
    "pageType": "order_status"
  },
  "_experience": {
    "analytics": {
      "customDimensions": {
        "eVars": {
          "eVar12": "shipment.deliveryExceptionType"
        }
      }
    }
  },
  "shipment": {
    "orderId": "{{orderId}}",
    "trackingNumber": "{{trackingNumber}}",
    "carrier": "{{carrier}}",
    "shipmentMode": "{{shipmentMode}}",
    "fulfillmentMethod": "{{fulfillmentMethod}}",
    "deliveryExceptionType": "{{deliveryExceptionType}}",
    "exceptionTimestamp": "{{exceptionTimestamp}}",
    "deliveryRegion": "{{deliveryRegion}}",
    "shippingTier": "{{shippingTier}}"
  }
}

SQL Queries

Google Analytics 4 (BigQuery)
-- ==========================================
-- 1. GOOGLE BIGQUERY SQL
-- ==========================================
DECLARE start_date DATE DEFAULT DATE_SUB(CURRENT_DATE(), INTERVAL 90 DAY);
DECLARE end_date DATE DEFAULT DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY);

WITH scans AS (
  -- Exception scans seen on tracking pages, one row per package scan, UTC timestamp (source rank 2)
  SELECT
    (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'tracking_number') AS tracking_number,
    LOWER(TRIM((SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'delivery_exception_type'))) AS raw_type,
    SAFE.TIMESTAMP((SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'exception_timestamp')) AS scan_ts,
    2 AS source_rank
  FROM `your-project.analytics_123456789.events_*`
  WHERE _TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(start_date, INTERVAL 1 DAY)) AND FORMAT_DATE('%Y%m%d', DATE_ADD(end_date, INTERVAL 1 DAY))
    AND event_name = 'page_view'
    AND (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'page_type') = 'order_status'
  UNION ALL
  -- OMS carrier exception events for the same packages (source rank 1, wins on conflict)
  SELECT tracking_number, LOWER(TRIM(exception_type)), scan_timestamp_utc, 1
  FROM `your-project.oms.carrier_events`
  WHERE event_category = 'exception'
),
mapped AS (
  -- Map raw codes to the fixed value list (attempted delivery = recipient_unavailable, unmapped = other); drop customer holds/reroutes and empty values
  SELECT
    tracking_number,
    scan_ts,
    source_rank,
    CASE
      WHEN raw_type IN ('weather', 'weather_delay', 'severe_weather') THEN 'weather'
      WHEN raw_type IN ('address_issue', 'incorrect_address', 'bad_address', 'incomplete_address') THEN 'address_issue'
      WHEN raw_type IN ('damaged', 'damage', 'package_damaged') THEN 'damaged'
      WHEN raw_type IN ('recipient_unavailable', 'attempted_delivery', 'delivery_attempted', 'notice_left') THEN 'recipient_unavailable'
      WHEN raw_type IN ('held_at_facility', 'facility_hold', 'held_at_terminal') THEN 'held_at_facility'
      ELSE 'other'
    END AS delivery_exception_type
  FROM scans
  WHERE tracking_number IS NOT NULL
    AND raw_type IS NOT NULL
    AND raw_type NOT IN ('', 'none', 'customer_hold', 'customer_requested_hold', 'customer_reroute', 'reroute_requested')
    AND DATE(scan_ts, 'UTC') BETWEEN start_date AND end_date
)
-- One value per package: OMS scans first, then the last exception scan, dated by the carrier exception scan (UTC)
SELECT
  tracking_number,
  DATE(scan_ts, 'UTC') AS exception_date,
  delivery_exception_type
FROM mapped
QUALIFY ROW_NUMBER() OVER (PARTITION BY tracking_number ORDER BY source_rank, scan_ts DESC) = 1;
Adobe Experience Platform (AEP Query Service)
-- ==========================================
-- 2. ADOBE AEP QUERY SERVICE SQL
-- ==========================================
WITH params AS (
  -- Relative reporting window (UTC dates)
  SELECT CAST(CURRENT_DATE - INTERVAL '90' DAY AS DATE) AS start_date, CAST(CURRENT_DATE - INTERVAL '1' DAY AS DATE) AS end_date
),
scans AS (
  -- Exception scans seen on tracking pages, one row per package scan, UTC timestamp (source rank 2)
  SELECT
    e.shipment.trackingNumber AS tracking_number,
    LOWER(TRIM(e.shipment.deliveryExceptionType)) AS raw_type,
    to_timestamp(e.shipment.exceptionTimestamp) AS scan_ts,
    2 AS source_rank
  FROM web_events_dataset e
  WHERE e.eventType = 'pageView'
    AND e.page.pageType = 'order_status'
  UNION ALL
  -- OMS carrier exception events for the same packages (source rank 1, wins on conflict)
  SELECT tracking_number, LOWER(TRIM(exception_type)), scan_timestamp_utc, 1
  FROM oms_carrier_events
  WHERE event_category = 'exception'
),
mapped AS (
  -- Map raw codes to the fixed value list (attempted delivery = recipient_unavailable, unmapped = other); drop customer holds/reroutes and empty values
  SELECT
    s.tracking_number,
    s.scan_ts,
    s.source_rank,
    CASE
      WHEN s.raw_type IN ('weather', 'weather_delay', 'severe_weather') THEN 'weather'
      WHEN s.raw_type IN ('address_issue', 'incorrect_address', 'bad_address', 'incomplete_address') THEN 'address_issue'
      WHEN s.raw_type IN ('damaged', 'damage', 'package_damaged') THEN 'damaged'
      WHEN s.raw_type IN ('recipient_unavailable', 'attempted_delivery', 'delivery_attempted', 'notice_left') THEN 'recipient_unavailable'
      WHEN s.raw_type IN ('held_at_facility', 'facility_hold', 'held_at_terminal') THEN 'held_at_facility'
      ELSE 'other'
    END AS delivery_exception_type
  FROM scans s
  CROSS JOIN params p
  WHERE s.tracking_number IS NOT NULL
    AND s.raw_type IS NOT NULL
    AND s.raw_type NOT IN ('', 'none', 'customer_hold', 'customer_requested_hold', 'customer_reroute', 'reroute_requested')
    AND CAST(s.scan_ts AS DATE) BETWEEN p.start_date AND p.end_date
)
-- One value per package: OMS scans first, then the last exception scan, dated by the carrier exception scan (UTC)
SELECT tracking_number, CAST(scan_ts AS DATE) AS exception_date, delivery_exception_type
FROM (
  SELECT m.*, ROW_NUMBER() OVER (PARTITION BY tracking_number ORDER BY source_rank, scan_ts DESC) AS rn
  FROM mapped m
) ranked
WHERE rn = 1;

Source Data

Digital Analytics (GA4 / Adobe Analytics) + Order Management (reconciliation)

Dependencies

Prerequisite: List the dependencies required for this Dimension

Events:

delivery-exception-occurrenceshipment-delay-notification

Dimensions:

Report Attributes

carrier delivery-region shipment-mode fulfillment-method shipping-tier

Segment Eligibility

true

Governance

Data SensitivityInternal

Governance

Created bydevyendarm
Created on9/23/2026
Last modified bydevyendarm
Last modified on9/23/2026
Version1.0.0
Validation stateqa passed
StatusPUBLISHED

GitHub

View related Pull Requestcatalog/dimensions/delivery-exception-type.yml

Community Discussion