← Back to Metrics

Average Search Depth

Also known as: Avg. Search Depth, Average Pages per Search

EngagementmetricE-commerce: Product Discovery & Merchandising (Search/Filters/PDP)E-commerce

Average page views a shopper makes after an on-site search: Search Depth (page views after a search) divided by unique searches. Higher depth means results lead shoppers further into the catalog.

Business Use Case

1️⃣ Merchandising sees depth fall for a top search term and reviews its result ranking and facet set.,2️⃣ Product compares depth before and after a search engine or relevance change to confirm shoppers browse further.,3️⃣ Merchandising reads low depth alongside Search Exits to find terms whose results end the visit.

Business Criticality

Medium

Journey / Navigation Area

Discovery

Owning Function

Merchandising

Scope

Event

Formula

Search Depth / Unique Searches, where Search Depth = COUNT(page_view after a search results page, same session, before the next search) and Unique Searches = COUNT(DISTINCT session × search_term)

Calculation Notes

1️⃣ Search Depth counts page_view events after a search results page in the same session, up to the next search or session end.,2️⃣ The results page itself is not counted; pagination or re-sorting of the same term's results adds no depth.,3️⃣ Denominator is unique searches: one per session and search_term, so refires and reloads of the same query count once.,4️⃣ Searches with no later page view (search exits) stay in the denominator with a depth of 0.,5️⃣ A session ends after 30 minutes of inactivity or at midnight; depth never carries into the next session.,6️⃣ Bot, internal and test traffic is excluded via traffic_type before both numerator and denominator are counted.

Technical Details

Measure TypeAverage
Aggregation WindowDaily, Weekly, Monthly

Events

PlatformEvent
Google Analytics 4search
Adobesearch

Data Mappings

W3 Data Layer
{
  "page": {
    "pageInfo": {
      "pageURL": "https://www.example.com/search?q=term",
      "onsiteSearchTerm": "term",
      "onsiteSearchResults": 10
    },
    "category": {
      "pageType": "search_results"
    },
    "attributes": {
      "traffic_type": "external"
    }
  },
  "event": [
    {
      "eventInfo": {
        "eventName": "search"
      }
    },
    {
      "eventInfo": {
        "eventName": "page_view"
      },
      "attributes": {
        "pageURL": "https://www.example.com/product/SKU-1",
        "pageType": "product_detail"
      }
    }
  ]
}
GA4 Data Layer
[
  {
    "event": "search",
    "search_term": "term",
    "search_results_count": 10,
    "page_location": "https://www.example.com/search?q=term",
    "page_type": "search_results",
    "traffic_type": "external"
  },
  {
    "event": "page_view",
    "page_location": "https://www.example.com/product/SKU-1",
    "page_type": "product_detail",
    "traffic_type": "external"
  }
]
Adobe Client Data Layer
[
  {
    "event": "search",
    "eventInfo": {
      "search_term": "term",
      "search_results_count": 10,
      "page_location": "https://www.example.com/search?q=term",
      "page_type": "search_results",
      "traffic_type": "external"
    }
  },
  {
    "event": "pageView",
    "eventInfo": {
      "page_location": "https://www.example.com/product/SKU-1",
      "page_type": "product_detail",
      "traffic_type": "external"
    }
  }
]
XDM Mapping
[
  {
    "eventType": "search",
    "identityMap": {
      "ECID": [
        {
          "id": "ECID-1",
          "authenticatedState": "ambiguous",
          "primary": true
        }
      ]
    },
    "web": {
      "webPageDetails": {
        "URL": "https://www.example.com/search?q=term"
      }
    },
    "_tenantId": {
      "searchTerm": "term",
      "searchResultsCount": 10,
      "pageType": "search_results",
      "trafficType": "external"
    }
  },
  {
    "eventType": "web.webpagedetails.pageViews",
    "identityMap": {
      "ECID": [
        {
          "id": "ECID-1",
          "authenticatedState": "ambiguous",
          "primary": true
        }
      ]
    },
    "web": {
      "webPageDetails": {
        "URL": "https://www.example.com/product/SKU-1",
        "pageViews": {
          "value": 1
        }
      }
    },
    "_tenantId": {
      "pageType": "product_detail",
      "trafficType": "external"
    }
  }
]

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);

-- Search and page_view events with page type and a session key that also splits at midnight (user_pseudo_id.ga_session_id.event_date)
WITH events AS (
  SELECT
    CONCAT(user_pseudo_id, '.', CAST((SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id') AS STRING), '.', event_date) AS session_key,
    event_name,
    event_timestamp,
    (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'page_type') AS page_type,
    (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'search_term') AS search_term,
    (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'traffic_type') AS traffic_type
  FROM `your-project.analytics_123456789.events_*`
  WHERE _TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', start_date) AND FORMAT_DATE('%Y%m%d', end_date)
    AND event_name IN ('search', 'page_view')
),

-- Bot, internal and test traffic removed before numerator and denominator are counted
clean AS (
  SELECT session_key, event_name, event_timestamp, page_type, search_term
  FROM events
  WHERE session_key IS NOT NULL
    AND IFNULL(traffic_type, 'external') NOT IN ('bot', 'internal', 'test')
),

-- First search per session: page views before it carry no search depth
first_search AS (
  SELECT session_key, MIN(event_timestamp) AS first_search_ts
  FROM clean
  WHERE event_name = 'search'
  GROUP BY session_key
),

-- Search Depth: page views after a search that are not results pages (page_type 'search_results' covers the results page, its pagination and re-sorts); each falls in exactly one search's window (up to the next search), so the total is the summed depth
depth AS (
  SELECT COUNT(*) AS search_depth
  FROM clean p
  JOIN first_search f ON f.session_key = p.session_key
  WHERE p.event_name = 'page_view'
    AND p.event_timestamp > f.first_search_ts
    AND IFNULL(p.page_type, '') != 'search_results'
),

-- Unique Searches: one per session and search_term, so refires and reloads count once and search exits stay in with depth 0
unique_searches AS (
  SELECT COUNT(DISTINCT CONCAT(session_key, '|', search_term)) AS unique_searches
  FROM clean
  WHERE event_name = 'search'
)

-- Average Search Depth = Search Depth / Unique Searches
SELECT ROUND(SAFE_DIVIDE(d.search_depth, u.unique_searches), 2) AS average_search_depth
FROM depth d
CROSS JOIN unique_searches u;
Adobe Experience Platform (AEP Query Service)
-- ==========================================
-- 2. ADOBE AEP QUERY SERVICE SQL
-- ==========================================
-- 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
),

-- Events with identity, page type, search term and traffic type
events AS (
  SELECT
    identityMap['ECID'][0].id AS ecid,
    timestamp,
    eventType,
    _tenantId.pageType AS page_type,
    _tenantId.searchTerm AS search_term,
    _tenantId.trafficType AS traffic_type
  FROM aep_web_events, params
  WHERE timestamp >= params.start_date
    AND timestamp < date_add(params.end_date, 1)
),

-- Sessions per ECID with a 30-minute inactivity timeout, split at midnight
sessionized AS (
  SELECT
    *,
    SESS_TIMEOUT(timestamp, 60 * 30) OVER (
      PARTITION BY ecid, to_date(timestamp) ORDER BY timestamp
      ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
    ) AS session
  FROM events
  WHERE ecid IS NOT NULL
),

-- Search and page view events only; bot, internal and test traffic removed before numerator and denominator are counted
clean AS (
  SELECT
    CONCAT(ecid, '.', CAST(to_date(timestamp) AS STRING), '.', CAST(session.num AS STRING)) AS session_key,
    eventType,
    timestamp,
    page_type,
    search_term
  FROM sessionized
  WHERE eventType IN ('search', 'web.webpagedetails.pageViews')
    AND COALESCE(traffic_type, 'external') NOT IN ('bot', 'internal', 'test')
),

-- First search per session: page views before it carry no search depth
first_search AS (
  SELECT session_key, MIN(timestamp) AS first_search_ts
  FROM clean
  WHERE eventType = 'search'
  GROUP BY session_key
),

-- Search Depth: page views after a search that are not results pages (page_type 'search_results' covers the results page, its pagination and re-sorts); each falls in exactly one search's window (up to the next search), so the total is the summed depth
depth AS (
  SELECT COUNT(*) AS search_depth
  FROM clean p
  JOIN first_search f ON f.session_key = p.session_key
  WHERE p.eventType = 'web.webpagedetails.pageViews'
    AND p.timestamp > f.first_search_ts
    AND COALESCE(p.page_type, '') != 'search_results'
),

-- Unique Searches: one per session and search_term, so refires and reloads count once and search exits stay in with depth 0
unique_searches AS (
  SELECT COUNT(DISTINCT CONCAT(session_key, '|', search_term)) AS unique_searches
  FROM clean
  WHERE eventType = 'search'
)

-- Average Search Depth = Search Depth / Unique Searches
SELECT ROUND(d.search_depth / NULLIF(u.unique_searches, 0), 2) AS average_search_depth
FROM depth d
CROSS JOIN unique_searches u;

Source Data

Digital Analytics (GA4)

Dependencies

Prerequisite: List the dependencies required for this Metric

Events:

site-searchpage-view

Dimensions:

internal-search-term

Report Attributes

internal-search-term search-results-count-band device-category traffic-source page-type

Recommended Reporting Views

Views
Site Search PerformanceProduct Discovery & Merchandising

Segment Eligibility

true

Governance

Data SensitivityInternal

Governance

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

GitHub

View related Pull Requestcatalog/metrics/average-search-depth.yml

Community Discussion