Update URL filter matching guidance for Points and Campaign page visits - #919
Conversation
Mautic PR #15979 unifies URL filter matching so plain text now matches anywhere in the visited URL as a case-insensitive substring across the Points 'Visits specific URL' action and the Campaign 'Visits a Page' decision. Correct the troubleshooting guidance that said a plain URL only matches exactly or requires a wildcard; note legacy wildcard patterns are still supported.
There was a problem hiding this comment.
Pull request overview
This PR updates the Mautic user documentation to reflect Mautic 7’s unified URL filter behavior for page-related flows: user-entered URL filter text now matches anywhere in the visited URL as a case-insensitive substring, while legacy wildcard patterns (e.g., trailing *) remain supported for prefix-style matching.
Changes:
- Updates Points troubleshooting guidance for “Visits specific URL” to describe substring, case-insensitive matching and retained wildcard support.
- Updates Campaign troubleshooting guidance for “Visits a Page” to describe the same matching behavior and clarifies the existing query-parameter/wildcard example.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| docs/points/points_troubleshooting.rst | Updates URL matching guidance for Points “Page visits not recognized” troubleshooting. |
| docs/campaigns/troubleshooting_campaigns.rst | Updates URL matching guidance for Campaign “Page visits aren’t recognized” troubleshooting, keeping wildcard examples. |
Suppressed comments (1)
docs/campaigns/troubleshooting_campaigns.rst:23
- "anchors a required prefix" is a bit misleading in the context of wildcard matching; the behavior being described is a prefix match based on the text before the trailing
*. Rewording helps avoid implying regex-style anchors.
Another example is if you want to associate different page hits with specific Campaigns. For example, if you have Campaign A and Campaign B and you want to use the same base URL and path for both Campaigns but differentiate with a query parameter. Here the trailing ``*`` anchors a required prefix, so each decision matches only its intended query parameter. For Campaign A, you can define a Visits a Page decision with ``https://example.com/my-page?utm_campaign=A*`` and for Campaign B, ``https://example.com/my-page?utm_campaign=B*``. A Contact only triggers the specific Campaign desired. If the goal is to trigger both Campaigns regardless of the query parameters, use ``https://example.com/my-page*``.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| #. Mautic executes Campaigns sequentially and won't repeat per Contact. If the Contact has already visited the Page while part of the Campaign and triggered the Visits a Page decision, then the Contact's subsequent visits won't re-trigger the actions associated with the decision. | ||
|
|
||
| #. Ensure that the URL in the Campaign action either matches exactly the URL visited, or use a wildcard. A URL can include the schema, host/domain, path, query parameters, and/or fragment. For example, if you have a URL of ``https://example.com`` and the page hit registers as ``https://example.com/index.php?foo=bar``, the Campaign decision won't trigger. However, if you use ``https://example.com*`` as the URL, it matches the rule and thus gets triggered. | ||
| #. Ensure that the URL in the Campaign decision appears somewhere in the visited URL. Mautic matches the URL you enter anywhere within the visited URL, and the match isn't case-sensitive. The Campaign decision triggers whenever that text appears. A URL can include the scheme, host or domain, path, query parameters, or fragment. |
| 2. The tracking of Point Actions is currently done once per Contact. This means that subsequent visits won't re-trigger the action if already triggered once. | ||
|
|
||
| 3. Ensure that the URL defined either matches exactly the URL visited or use a wildcard. A URL can include the schema, host/domain, path, query parameters, and/or fragment. | ||
| 3. Ensure that the URL you define appears somewhere in the visited URL. Mautic matches the URL you enter anywhere within the visited URL, and the match isn't case-sensitive. The Point Action triggers whenever that text appears. A URL can include the scheme, host or domain, path, query parameters, or fragment. |
|
@promptless-for-oss please review the feedback from copilot, can we be clearer in this case? |
|
Thanks @RCheesley — taking a look at Copilot's feedback now and reworking the wildcard/prefix-matching wording so it's clearer and doesn't imply regex-style anchoring. I'll follow up here with the updates. |
|
Reviewed Copilot's feedback — three wording points across the campaigns and points troubleshooting pages: the trailing- |
Address GitHub Copilot review points on PR mautic#919: - Reword the trailing `*` guidance so it describes a prefix match on the literal text before it, not a regex-style anchor. - Reword the URL-condition sentences so they read as the matching condition being satisfied, not as repeat/per-visit triggering, keeping them consistent with the once-per-Contact behavior stated earlier.
| 2. The tracking of Point Actions is currently done once per Contact. This means that subsequent visits won't re-trigger the action if already triggered once. | ||
|
|
||
| 3. Ensure that the URL defined either matches exactly the URL visited or use a wildcard. A URL can include the schema, host/domain, path, query parameters, and/or fragment. | ||
| 3. Ensure that the URL you define in the Point Action appears somewhere in the visited URL. Mautic matches the URL you enter anywhere within the visited URL, and the match isn't case-sensitive. If that text appears in the visited URL, it satisfies the Point Action's URL condition. The once-per-Contact behavior noted earlier still applies, so subsequent visits won't re-trigger it. A URL can include the scheme, host or domain, path, query parameters, or fragment. |
There was a problem hiding this comment.
PR mautic/mautic#15979 routes the Point Action "Visits specific URL" filter through UrlMatcher::hasMatch(), which uses preg_match('/'.preg_quote($url,'/').'/i', ...) — a case-insensitive substring match anywhere in the visited URL, confirming "Mautic matches the URL you enter anywhere within the visited URL, and the match isn't case-sensitive."
| 3. Ensure that the URL you define in the Point Action appears somewhere in the visited URL. Mautic matches the URL you enter anywhere within the visited URL, and the match isn't case-sensitive. If that text appears in the visited URL, it satisfies the Point Action's URL condition. The once-per-Contact behavior noted earlier still applies, so subsequent visits won't re-trigger it. A URL can include the scheme, host or domain, path, query parameters, or fragment. | ||
|
|
||
| For example, if you have a URL of ``https://example.com`` and the page hit registers as ``https://example.com/index.php?foo=bar``, the point action won't be recognized. However, if you use ``https://example.com*`` as the URL, it matches the rule and thus gets triggered. No newline at end of file | ||
| For example, if you have a URL of ``https://example.com`` and the page hit registers as ``https://example.com/index.php?foo=bar``, the Point Action now triggers, because the defined text appears in the visited URL. Legacy wildcard patterns such as ``https://example.com*`` are also supported, and a trailing ``*`` still matches any visited URL that begins with the literal text before it. No newline at end of file |
There was a problem hiding this comment.
PR mautic/mautic#15979: UrlMatcher::hasMatch() checks isLegacyWildcardPattern($url) (true when the filter contains , ?, or [) and calls fnmatch($url, $urlToFind, FNM_CASEFOLD) before falling back to substring match. This confirms both that a defined URL of https://example.com now matches https://example.com/index.php?foo=bar via substring matching, and that legacy wildcard patterns like https://example.com remain supported with the trailing * still requiring a literal prefix.
| #. Mautic executes Campaigns sequentially and won't repeat per Contact. If the Contact has already visited the Page while part of the Campaign and triggered the Visits a Page decision, then the Contact's subsequent visits won't re-trigger the actions associated with the decision. | ||
|
|
||
| #. Ensure that the URL in the Campaign action either matches exactly the URL visited, or use a wildcard. A URL can include the schema, host/domain, path, query parameters, and/or fragment. For example, if you have a URL of ``https://example.com`` and the page hit registers as ``https://example.com/index.php?foo=bar``, the Campaign decision won't trigger. However, if you use ``https://example.com*`` as the URL, it matches the rule and thus gets triggered. | ||
| #. Ensure that the URL in the Campaign decision appears somewhere in the visited URL. Mautic matches the URL you enter anywhere within the visited URL, and the match isn't case-sensitive. If that text appears in the visited URL, it satisfies the decision's URL condition. The once-per-Contact behavior noted earlier still applies, so subsequent visits won't re-trigger it. A URL can include the scheme, host or domain, path, query parameters, or fragment. |
There was a problem hiding this comment.
PR mautic/mautic#15979 changes the Campaign "Visits a Page" decision's URL/Referrer matching from fnmatch() to UrlMatcher::hasMatch($limitToUrls, $pageUrl), which performs a case-insensitive substring match anywhere in the visited URL, confirming "Mautic matches the URL you enter anywhere within the visited URL, and the match isn't case-sensitive."
| #. Ensure that the URL in the Campaign decision appears somewhere in the visited URL. Mautic matches the URL you enter anywhere within the visited URL, and the match isn't case-sensitive. If that text appears in the visited URL, it satisfies the decision's URL condition. The once-per-Contact behavior noted earlier still applies, so subsequent visits won't re-trigger it. A URL can include the scheme, host or domain, path, query parameters, or fragment. | ||
|
|
||
| Another example is if you want to associate different page hits with specific Campaigns. For example, if you have Campaign A and Campaign B and you want to use the same base URL and path for both Campaigns but differentiate with a query parameter. For Campaign A, you can define a Visits a Page decision with ``https://example.com/my-page?utm_campaign=A*`` and for Campaign B, ``https://example.com/my-page?utm_campaign=B*``. A Contact only triggers the specific Campaign desired. If the goal is to trigger both Campaigns regardless of the query parameters, use ``https://example.com/my-page*``. No newline at end of file | ||
| For example, if you have a URL of ``https://example.com`` and the page hit registers as ``https://example.com/index.php?foo=bar``, the Campaign decision now triggers, because the defined text appears in the visited URL. Legacy wildcard patterns such as ``https://example.com*`` are also supported, and a trailing ``*`` still matches any visited URL that begins with the literal text before it. |
There was a problem hiding this comment.
PR mautic/mautic#15979: UrlMatcher::hasMatch() now matches a defined URL of https://example.com against a page hit of https://example.com/index.php?foo=bar as a substring (previously required a wildcard), and isLegacyWildcardPattern()/fnmatch(..., FNM_CASEFOLD) preserves legacy wildcard patterns such as https://example.com*, with a trailing * still anchoring a required literal prefix.
| Another example is if you want to associate different page hits with specific Campaigns. For example, if you have Campaign A and Campaign B and you want to use the same base URL and path for both Campaigns but differentiate with a query parameter. For Campaign A, you can define a Visits a Page decision with ``https://example.com/my-page?utm_campaign=A*`` and for Campaign B, ``https://example.com/my-page?utm_campaign=B*``. A Contact only triggers the specific Campaign desired. If the goal is to trigger both Campaigns regardless of the query parameters, use ``https://example.com/my-page*``. No newline at end of file | ||
| For example, if you have a URL of ``https://example.com`` and the page hit registers as ``https://example.com/index.php?foo=bar``, the Campaign decision now triggers, because the defined text appears in the visited URL. Legacy wildcard patterns such as ``https://example.com*`` are also supported, and a trailing ``*`` still matches any visited URL that begins with the literal text before it. | ||
|
|
||
| Another example is if you want to associate different page hits with specific Campaigns. For example, if you have Campaign A and Campaign B and you want to use the same base URL and path for both Campaigns but differentiate with a query parameter. Here the trailing ``*`` matches any visited URL that begins with the literal text before it, so each decision matches only its intended query parameter. For Campaign A, you can define a Visits a Page decision with ``https://example.com/my-page?utm_campaign=A*`` and for Campaign B, ``https://example.com/my-page?utm_campaign=B*``. A Contact only triggers the specific Campaign desired. If the goal is to trigger both Campaigns regardless of the query parameters, use ``https://example.com/my-page*``. No newline at end of file |
There was a problem hiding this comment.
PR mautic/mautic#15979: isLegacyWildcardPattern() (strpbrk($url, '?[')) routes any filter containing * to fnmatch() instead of substring matching, so trailing- patterns like https://example.com/my-page?utm_campaign=A* still anchor a required literal prefix, letting Campaign A and Campaign B differentiate by query parameter.
|
Thanks — good catch. We've reworded the flagged guidance in both troubleshooting pages (
Vale passes on both files. The changes are pushed (SHA |
Open in Promptless
Mautic 7 (via mautic/mautic PR #15979) unifies how URL filters match across page-related flows. Plain text you enter in a URL filter now matches anywhere within the visited URL as a case-insensitive substring — the same behavior as email click decisions — instead of requiring an exact match or a shell wildcard. Legacy wildcard patterns such as
https://example.com*are still supported, so existing saved filters keep working.Two troubleshooting passages documented the old wildcard-only behavior and are now inaccurate. This corrects them:
docs/points/points_troubleshooting.rst— the "Page visits not recognized" item for the Points 'Visits specific URL' action.docs/campaigns/troubleshooting_campaigns.rst— the URL-matching item for the Campaign 'Visits a Page' decision (the A/B query-parameter example, which relies on wildcards, is retained since wildcards still work).Trigger Events