URL pattern matching

Userflow lets you segment and personalize content using URL pattern matching. Examples:

  • Start a flow on specific URLs
  • Advance to the next step in a flow when user navigates to a specific URL
  • Mark a checklist task as completed if user has visited a URL

We use a simple URL pattern format described here.

Quick examples

  • Specific path (no subpaths) on any domain:

    • /app/dashboard
  • Including subpaths:

    • /app* - will match /app, /app/dashboard and /app/projects
    • Note that this will also match /apple, /applications etc.
  • Only subpaths:

    • /app/* - will match /app/dashboard and /app/projects, but not /app
  • Dynamic path segment:

    • /app/:company/projects - will match /app/apple/projects and /app/banana/projects, but not /app/apple/projects/new
  • Mix dynamic path segment and subpaths:

    • /app/:company/projects/* - will match /app/apple/projects/123
  • Specific domain on any path:

    • app.com - will match app.com, but not www.app.com
  • Dynamic subdomain:

    • :subdomain.app.com - will match apple.app.com and banana.app.com, but not app.com or multiple.levels.app.com
  • Mix domain and path:

    • company.com/app/:company/projects*

URL parts

URLs consist of the following parts:

https://my.app.com/acme-inc/dashboard?tab=analytics#charts
\___/   \________/\_________________/ \___________/ \____/
  |         |              |                |          |
scheme    domain          path            query     fragment

scheme: https
domain: my.app.com
path: /acme-inc/dashboard
query: tab=analytics
fragment: charts

When writing URL patterns, all parts are optional. If a part is left out, it’ll match anything.

Each part has slightly different rules.

Scheme

The scheme is what comes before :// in a URL.

https://my.app.com/acme-inc/dashboard?tab=analytics#charts
\___/
  |
scheme

The scheme is almost always either http or https. You only need to specify scheme in your URL patterns if you care about whether the user is on http or https. Usually your server takes care of redirecting users to one or the other.

Wildcard scheme

You can specify *:// to match any scheme, which is the same as leaving it out completely. I.e. these 2 patterns are equivalent:

  • *://app.com/settings
  • app.com/settings

Domain

The domain part is what comes after :// and before the path’s first /.

https://my.app.com/acme-inc/dashboard?tab=analytics#charts
        \________/
            |
          domain

Dynamic subdomain

To match dynamic subdomains (e.g. apple.app.com and banana.app.com), use a colon and an arbitrary name such as :company.app.com. :company will match a non-empty subdomain, meaning it will not include .. The name after : does not matter and is currently not used for anything.

:company.app.com and :subdomain.app.com are equivalent and will match:

  • apple.app.com
  • banana.app.com

They will not match:

  • app.com (missing subdomain)
  • more.apple.app.com (more subdomains)

Wildcard domains

You can also use * as a wildcard character to match any number of subdomains.

*.app.com will match both one.app.com and one.two.app.com, but not app.com.

*app.com will match app.com, but will also match myapp.com.

Path

The path part is what comes after the domain and before the query (starting with ?), or the fragment (starting with #) if there’s no query.

https://my.app.com/acme-inc/dashboard?tab=analytics#charts
                  \_________________/
                           |
                          path

Important: Paths MUST start with a slash (/). The URL pattern app/projects will consider app as the domain, and will match full URLs such as https://app/projects (which doesn’t really make sense). The right pattern here would be /app/projects.

Dynamic path segments

To match dynamic path segments (e.g. /app/apple/projects and /app/banana/projects), use a colon and an arbitrary name such as /app/:company/projects. :company will match a non-empty path segment, meaning it will not include /. The name after : does not matter and is currently not used for anything.

/app/:company/projects and /app/:slug/projects are equivalent and will match:

  • /app/apple/projects
  • /app/banana/projects

They will not match:

  • /app/projects (missing path segment)
  • /app/apple/projects/123 (deeper path)

Wildcard paths

You can also use * as a wildcard character to match nested paths.

/app/* will match both /app/one and /app/one/two, but not /app.

/app* will match /app, but will also match /applications.

/*/projects will match /app/projects and /app/one/two/three/projects.

You can mix wildcards and dynamic path segments at will. Example: /*/customers/:customer/invoices/:invoice/*

Query

The query is what comes after ? and before the fragment (starting with #), if any.

https://my.app.com/acme-inc/dashboard?tab=analytics#charts
                                      \___________/
                                            |
                                          query

A URL can contain multiple query parameters separated by ampersands (&), as in ?fruit=apple&tab=analytics. Query parameters are matched one by one. Order of query parameters does not matter. Extra, non-matched query parameters, are not considered.

?fruit=apple&tab=analytics will match:

  • ?fruit=apple&tab=analytics
  • ?tab=analytics&fruit=apple (different order is OK)
  • ?other=test&fruit=apple&another=test&tab=analytics (extra parameters is OK)

But will not match:

  • ?fruit=apple (parameter is missing)
  • ?fruit=banana&tab=analytics (wrong value)

Wildcard query parameter values

You can use * to match any value in individual query parameters. It’s required that the query parameter is present though.

?param=a* will match:

  • ?param=apple

It will not match:

  • ?param=banana (does not start with a)
  • ?param (no value)
  • ?param2=one (wrong parameter name)

?param=* will match:

  • ?param=one
  • ?param (no value, but present)

It will not match:

  • ?param2=one (wrong parameter name)

Fragment

The fragment is what comes after #.

https://my.app.com/acme-inc/dashboard?tab=analytics#charts
                                                    \____/
                                                       |
                                                    fragment

Since the fragment is often used like a path in single-page applications, fragment obeys the same rules as Path.

To match a dynamic fragment segment: #/projects/:project/dashboard.

Using wildcard: #/projects/:project/dashboard/*.

Got questions? We're here for you!

The best way to get help is to
We usually reply within 5 minutes
You can also send an email to support@getuserflow.com
We usually reply within a few hours