DQL examples

  • Latest Dynatrace
  • Reference
  • 1-min read
  • Published Aug 19, 2025
  • Preview

Use DQL queries to extract data based on RUM metrics, sessions, and events. Below are some examples to get more familiar with DQL and RUM data.

Frontend Performance

Core Web Vitals - Largest contentful paint (LCP)

The example below creates a time-series graph of the 75th percentile for LCP across all pages combined over the selected time frame as well as an average value in milliseconds from that timeseries.

timeseries LCP = percentile(dt.frontend.web.page.largest_contentful_paint, 75)
//filter to specific application on the next line
//, filter: dt.rum.application.entity == "Application-ID" //Optional: Application Filter
| fieldsAdd LCP_average_value = arrayAvg(LCP) //this value is in miliseconds

Core Web Vitals - Largest contentful paint (LCP) DQL query

LCP Times per Page and Elements Triggering LCP

The DQL query below queries for the 75th percentile of LCP for any page, groups by the resource URL, and identifies the XPath and Tag Name that trigger LCP time.

  • Core Web Vitals are reported at the page summary event
  • All colors for LCP values in the table are aligned with Google's recommendations

If you want to filter to a specific application, uncomment line 3 by removing the backslashes // and add your application ID. To find your application ID:

  1. Go to Custom Applications.
  2. Select your application and select > Edit.
  3. Once in the Instrumentation wizard, you can find the Application ID as a query parameter in the URL. For example: appId=CUSTOM_APPLICATION-211RD6FH20C8114G.
fetch user.events
//filter to specific application on the next line
//| filter dt.rum.application.entity == "Application-ID" //Optional: Application Filter
| filter characteristics.has_page_summary
| filter isNotNull(web_vitals.largest_contentful_paint)
| fields page.name, web_vitals.largest_contentful_paint, lcp.url, lcp.ui_element.tag_name, lcp.ui_element.xpath, lcp.status
| summarize LCP = percentile(web_vitals.largest_contentful_paint, 75), by: {page.name, lcp.url, lcp.ui_element.xpath, lcp.ui_element.tag_name}
| sort LCP desc

LCP Times per Page and Elements Triggering LCP DQL query

Behavioural Insights

With the example below, you can see the list of the top user interactions for specific interaction names such as click, touch, or keypress, and sort them in a table by the count of users, sessions, or user interactions.

fetch user.events
| filter (characteristics.has_user_interaction in(interaction.name, {"click", "touch", "key_press"}))
| summarize {
sessions = countDistinct(dt.rum.session.id),
User_Interactions = countIf(characteristics.has_user_interaction == TRUE AND in(interaction.name, {"click", "touch", "key_press"}))
}, by: {Elements = ui_element.resolved_name, Type = ui_element.tag_name, Frontend = dt.rum.application.entity}
| sort User_Interactions desc
  • To see how many times a user clicks a button, use this DQL query:

    fetch user.events
    | filter (characteristics.has_user_interaction == TRUE AND in(interaction.name, {"click", "touch", "key_press"}))
    | summarize {
    Sessions = countDistinct(dt.rum.session.id),
    User_Interactions = countIf(characteristics.has_user_interaction == TRUE AND in(interaction.name, {"click", "touch", "key_press"}))
    }, by: {element = ui_element.resolved_name, Type = ui_element.tag_name, Frontend = dt.rum.application.entity}
    | sort User_Interactions desc
    | filter Frontend == "APPLICATION-ID"
    | filter Type == "button"
    | filter Elements == "Close details"

    How many times a user clicks a button - DQL query

  • In this example, we're using the navigation characteristics of user events that can be found in the Semantic Dictionary. There are different ways to summarize such as by page.detected_name, page.name, page.url.full, page.url.path and sorted by desceding number of sessions:

    fetch user.events
    | filter characteristics.has_navigation == true
    | summarize {
    Sessions = countDistinct(dt.rum.session.id),
    URLs = collectDistinct(page.url.full)
    }, by: {Pages = page.detected_name}
    | sort Sessions desc
  • Here, you can find out the page load time per session for all page URLs. You can then filter by a specific page and derive further statistics:

    fetch user.events
    | filter characteristics.has_page_summary
    | fields page.url.full, dt.rum.session.id, duration
    | limit 20
  • Now, let's see a hint from internal adoption within Dynatrace. In this example, we show from which pages users go to the main notebook page:

    fetch user.events
    | filter (characteristics.has_navigation == TRUE)
    | filter page.url.path == "/ui/apps/dynatrace.notebooks/" and page.source.url.path != "/ui/apps/dynatrace.notebooks/"
    | summarize sessions = countDistinct(dt.rum.session.id) by:page.source.url.path
    | sort sessions desc

    And below is an example of outgoing pages showing which pages are visited after:

    fetch user.events
    | filter (characteristics.has_navigation == TRUE)
    | filter not contains(page.url.path, "/ui/apps/dynatrace.notebooks/") and page.source.url.path != "/ui/apps/dynatrace.notebooks/"
    | summarize by:{page.url.path}, sessions = countDistinct(dt.rum.session.id)
    | sort sessions desc
  • To see how many sessions are considered a bounce, let's take a custom definition of a bounce, for example, sessions with less than one page navigation. This query is better suited for historical timeframes:

    fetch user.sessions
    | fieldsAdd bounced = navigation_count + page_summary_count <= 1
    | summarize by:{bounced}, bounced_count = count()
  • To attribute adoption to campaigns through UTM tags, you can use the following DQL query:

    fetch user.events
    | filter characteristics.has_navigation == TRUE
    | fields page.url.path, page.url.query, id
    | filterOut isNull(page.url.query)
    | parse page.url.query, "ARRAY{LD:key('&'| EOF)}*:params"
    | expand params
    | parse decodeUrl(params), "LD:key '=' LD:value"
    | filter in(key, array("utm_campaign", "utm_content", "utm_medium", "utm_source", "utm_term"))
    | summarize by:{key, value}, count = countDistinct(id)
    | sort count desc

Troubleshooting

Error Counts by Error Type

You can leverage the metric dt.frontend.error.count and see the errors of a specific frontend or all your frontends.

timeseries { sum(dt.frontend.error.count), by:{error.type }}

Error Counts by Error Type DQL query

JavaScript Error Counts

Another way to analyse is by leveraging user events, to count JavaScript exceptions.

fetch user.events
| filter characteristics.has_exception
| filter dt.rum.agent.type == "javascript"
| makeTimeseries
count = count()

Javascript Error Counts DQL query

Related tags
Digital Experience