URL rewrite for Google analytics - asp.net

I have searched through many S.O. questions and answers, but haven't seen a good solution for this. I have already created and well-established SEO URLs in my web.config file. I was using a rewriteMap to basically turn my product pages into any URL that I needed.
Here is what I have to do this:
<rule name="Redirect Rule" enabled="true" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{RedirectMapName:{REQUEST_URI}}" pattern="(.+)" />
</conditions>
<action type="Redirect" url="{C:1}" appendQueryString="false" redirectType="Permanent" />
</rule>
<rule name="Rewrite Rule" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{RewriteMapName:{REQUEST_URI}}" pattern="(.+)" />
</conditions>
<action type="Rewrite" url="{C:1}" />
</rule>
What is being requested now is to add in Google Analytics parameters in order to track campaigns. If I simply add in the parameters, it will of course, give me a 404 error. I am now trying to get these SEO URLs to pick up these parameters, but getting quite frustrated.
If I remove the query string, Google Analytics will not pick it up since it is a client side script. Something like this might be close, but I am not pointing to any specific page.
URL Rewrite with Query String
This is how I remove the querystring:
<rule name="Subject redirect with query" stopProcessing="true">
<match url="^(.*)" />
<conditions trackAllCaptures="true">
<add input="{QUERY_STRING}" pattern="^utm_source=([^=&]+)&utm_medium=([^=&]+)&utm_campaign=([^=&]+)&?(.*)$" />
</conditions>
<action type="Redirect" url="{R:1}" appendQueryString="false" redirectType="Permanent" />
</rule>
Summed up, how do I turn this:
https://www.example.com/fancy-url
to this
https://www.example.com/fancy-url?utm_source=Targeted_Email&utm_medium=email&utm_campaign=campaigntag

After much frustration, I was able to figure this out. The query string was okay, but one of the settings was preventing the rest of the rules to be processed. After the rule name, I had stop processing set to true. When I looked at it in IIS, the setting is much more descriptive. It says "Stop processing of subsequent rules". Once I removed that and moved this above my other rules, worked perfectly.
<rule name="Google Query string">
<match url="(.*)$" />
<conditions>
<add input="{QUERY_STRING}" pattern="utm_source=([^=&]+)&utm_medium=([^=&]+)&utm_campaign=([^=&]+)&?(.*)$" />
</conditions>
<action type="Rewrite" url="{R:0}" appendQueryString="false" />
</rule>

Related

Combine several 301 redirects into one for ASP.NET URL Rewrite module

I am trying to move a complex redirect logic implemented in Global.asax into a set of rules for the IIS URL Rewrite module in a classic ASP.NET website. Shortly, the logic must redirect requests like
{http|https}://[www.]ourdomain.com/[Home/]Products/old-product-name/page.aspx
to
https://ourdomain.com/new-product-name/
(optional and variable parts are in square and curly brackets).
The first 3 main things I implemented with URL Rewrite rules are the followings:
<rule name="Redirect to HTTPS">
<match url=".*" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Permanent" />
</rule>
<rule name="Canonical Host Name">
<match url="(.*)" />
<conditions>
<add input="{HTTP_HOST}" negate="true" pattern="^ourdomain\.com$" />
</conditions>
<action type="Redirect" url="https://ourdomain.com/{R:1}" redirectType="Permanent" />
</rule>
<rule name="Default Page">
<match url="(.*)default.aspx" />
<conditions>
<add input="{REQUEST_URI}" negate="true" pattern="-default.aspx$" />
</conditions>
<action type="Redirect" url="{R:1}" redirectType="Permanent" />
</rule>
These rules allow to redirect requests like http://www.ourdomain.com/product-name/default.aspx to https://ourdomain.com/product-name.
However, the browser developer tools report that this conversion causes 301 redirects. I tried to find a solution of this redirect chain problem in the Internet and found this post. After reading it, I managed to recode my rules to have just one final 301 redirect with URL rewriting:
<rule name="Redirect to HTTPS">
<match url=".*" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Rewrite" url="_{REQUEST_URI}" redirectType="Permanent" />
</rule>
<rule name="Canonical Host Name">
<match url="(.*)" />
<conditions>
<add input="{HTTP_HOST}" negate="true" pattern="^ourdomain\.com$" />
</conditions>
<action type="Rewrite" url="_{R:1}" redirectType="Permanent" />
</rule>
<rule name="Default Page">
<match url="(.*)default.aspx" />
<conditions>
<add input="{REQUEST_URI}" negate="true" pattern="-default.aspx$" />
</conditions>
<action type="Rewrite" url="_{R:1}" redirectType="Permanent" />
</rule>
<rule name="FINAL REDIRECT" stopProcessing="true">
<match url="^(_+)(.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{HTTP_METHOD}" pattern="GET" />
</conditions>
<action type="Redirect" url="https://ourdomain.com{R:2}" />
</rule>
However, this approach looks non-natural. It makes hard adding new rules because of these workarounds with the underscore character. And maybe, such several rewrite operations for one request may impact on the website performance.
Is there another, more elegant solution, of the 301 redirect chain problem for the URL Rewrite module?
This is not a limitation of IIS Url Rewrite, but the way the web works. A redirection sends a header to the browser telling it that it should navigate to another place. If you have 3 rules that apply to the same original request, and the 3 apply a redirection, then you'll always get 3 redirections no matter how you do it: IIS Url Rewrite, Apache .htaccess or your own custom code.
The solution you've implemented is a "patch" to change several redirections into internal rewrites in the server and a final "catch" of those special rewrites to transform them into a unique redirection at the end (BTW, if you have any real page that strats with _ you won't be able to access it with this extra rule). That's not bad and won't affect your performance, but it's ugly.
I'm not a SEO expert but I think the 301 chaining thing to reach a final similar URL won't hurt your SEO at all in recent times, if that's what worries you (read the final part specially). And being 301 redirects they will affect only the first visit of your users, so probably won't hurt your loading times or conversions either anyway.
However, if you want to avoid that, try to make a single rule for your purpose, doing all the transformations at once. In your case, you want to transform this:
{http|https}://[www.]ourdomain.com/[Home/]Products/old-product-name/page.aspx
(I guess /Home/ can be present sometimes or not)
into this:
https://ourdomain.com/new-product-name/
Then you can use this single rule:
<rule name="New URLs!!" stopProcessing="true">
<match url="^(Home/){0,1}Products/(.+?/).+.aspx" />
<conditions logicalGrouping="MatchAny">
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
<add input="{HTTP_HOST}" negate="true" pattern="^ourdomain\.com$" />
</conditions>
<action type="Redirect" url="https://ourdomain.com/{R:2}" redirectType="Permanent" />
</rule>
and you will transform everything with a single rule (so, just one redirect). The regular expression in the match URL part will identify this specific kind of URL (old product URLs) and the conditions (matching any of them) will take care of the HTTPs and domain change. The stopProcessing="true" will keep other rules to act, and you'll have this specific kind of URLs under control.
Please note that I've not tested this rule and maybe it has minor problems. But you get the idea...
You'll need extra rules after this one to take care of other less-specific URLs, such as your general HTTP to HTTPS or canonical domain rules. But in the case you want to resolve, this will achieve what you want in a single step.

web.config Redirect Rule - Match URL

This seems to be a pretty straight forward change, however it's not matching the URL and none of the answers on stackoverflow seem to address this simple use of redirect rules. I believe it has something to do with the '?id=XXXX' portion of the URL.
We have some old versions of pages, which I am trying to add redirects to the new version of the pages.
Here's an example of my rules:
<rule name="old_Page" stopProcessing="true">
<match url="^Page.aspx?id=12345"/>
<action type="Redirect" url="http://www.example.com/newPage.aspx" redirectType="Permanent" />
</rule>
Any help would be most appreciated.
I used a different method to create Static Redirects in the web.config from this article:
https://www.iis.net/learn/extensions/url-rewrite-module/using-rewrite-maps-in-url-rewrite-module
<rewrites>
<rules>
<rule name="Redirect Rule" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{StaticRedirects:{REQUEST_URI}}" pattern="(.+)" />
</conditions>
<action type="Redirect" url="http://www.example.com{C:1}" appendQueryString="False" redirectType="Permanent" />
</rule>
</rules>
<rewriteMaps>
<rewriteMap name="StaticRedirects">
<add key="Page.aspx?id=12345" value="/newPage.aspx" />
</rewriteMap>
</rewriteMaps>
</rewrites>
I can add as many redirects as I like in the rewrite map section by adding additional keys.

IIS URL Rewrite with multiple query string

Im really new in URL Rewriting and trying to rewrite / redirect multiple query but seems not working. Since this is the search result and comes with different filtering the queries may vary. For example is some search we may have the query of t1=something and in the other we may have t2=somethingelse and sometimes we may combine them like: t1=something&t2=somethingelse
Im using IIS7 with web.config and here is what I have done so far:
This is my example link
www.website.com/search/?t1=first&t2=second
I have tried the following and non of them actually worked:
(1)
<rewrite>
<rules>
<rule name="first" stopProcessing="true">
<match url="search/" />
<conditions trackAllCaptures="true">
<add input="{QUERY_STRING}" pattern="t1=([0-9a-zA-Z]+)" />
</conditions>
<action type="Redirect" url="search/{C:1}/" appendQueryString="false" />
</rule>
<rule name="second" stopProcessing="true">
<match url="search/" />
<conditions trackAllCaptures="true">
<add input="{QUERY_STRING}" pattern="t2=([0-9a-zA-Z]+)" />
</conditions>
<action type="Redirect" url="search/{C:1}/" appendQueryString="false" />
</rule>
</rules>
</rewrite>
(2)
<rule name="a" stopProcessing="true">
<match url="search2/" />
<conditions trackAllCaptures="true">
<add input="{QUERY_STRING}" pattern="t1=([0-9a-zA-Z]+)" />
<add input="{QUERY_STRING}" pattern="t2=([0-9a-zA-Z]+)" />
</conditions>
<action type="Redirect" url="search2/{C:1}/{C:2}" appendQueryString="false" />
</rule>
I would really appreciate any help.
Thanks.
Also, this post might provide the answer -
Tracking Capture Groups Across Conditions setting
EDIT: the example from the link above
Note the trackAllCaptures=true
<rule name="Back-references with trackAllCaptures set to true">
<match url="^article\.aspx" >
<conditions trackAllCaptures="true">
<add input="{QUERY_STRING}" pattern="p1=([0-9]+)" />
<add input="{QUERY_STRING}" pattern="p2=([a-z]+)" />
</conditions>
<action type="Rewrite" url="article.aspx/{C:1}/{C:2}" /> <!-- rewrite action uses back-references to both conditions -->
</rule>
I thought I'd share a link of what I had found -
possible answer here
Also, to separate multiple parameters you can use a pipe operator. For example, something like this:
parm1=(\w+)|parm2=(\w+)
apply target URL with {C:1} and {C:2}
So, URL like this:
yourapp/list.aspx?parm1=abc&parm2=123
will result in back references as follows - {C:1}=abc and {C:2}=123

Conditional query string redirect

I'm trying to redirect requests that have a query string to a different domain name.
I've got a short url, http://short.url and I want to redirect http://short.url?hello to http://long.url/?hello. So the query string has to be kept by the redirect. To make things more complicated, I would like to rediect http://short.url?hello,hello2 to http://long.url/advanced.aspx/?hello,hello2.
Here is the rule I've got now (only dealing with the first part of my question)
<rewrite>
<rules>
<rule name="test" patternSyntax="ECMAScript" stopProcessing="true">
<match url="~/?\w+" />
<action type="Redirect" url="http://long.url/?{R:0}" redirectType="Found" />
</rule>
</rules>
</rewrite>
However, I am not seeing any redirects. Also, is there a better way to do this? Basically I just want to setup a shortcut to pass queries to a website. These are not meant to be permanent so I'm using redirectType="Found".
In case anyone is looking to do this:
<rules>
<rule name="Basic" patternSyntax="ECMAScript" stopProcessing="true">
<match url="\w*" />
<action type="Redirect" url="http://longurl.com" redirectType="Found" />
<conditions>
<add input="{QUERY_STRING}" pattern="\w+" />
<add input="{QUERY_STRING}" pattern="\," negate="true" />
</conditions>
</rule>
<rule name="Advanced" patternSyntax="ECMAScript" stopProcessing="true">
<match url="\w*" />
<action type="Redirect" url="http://longurl.com/advanced.aspx" redirectType="Found" />
<conditions>
<add input="{QUERY_STRING}" pattern="^\w+(?=\,)" />
</conditions>
</rule>
</rules>

Bidirectional URL Rewriting/Redirecting in IIS7.5

First off, I'd like to apologise for the ludicrous title. I'm not trying to sound cool or clever by using the word 'bidirectional', I just genuinely couldn't think of another way to describe it. Promise.
On to my problem. I have the following in the <system.webserver>/<rewrite>/<rules> section of my Web.config.
<!-- Who We Are -->
<rule name="1A">
<match url="^whoweare\.aspx$" />
<action type="Redirect" url="who-we-are" redirectType="Permanent" />
</rule>
<rule name="1B">
<match url="^who-we-are$" />
<action type="Rewrite" url="whoweare.aspx" />
</rule>
<!-- What We Do -->
<rule name="2A">
<match url="^whatwedo\.aspx$" />
<action type="Redirect" url="what-we-do" redirectType="Permanent" />
</rule>
<rule name="2B">
<match url="^what-we-do$" />
<action type="Rewrite" url="whatwedo.aspx" />
</rule>
Now this works tremendously. Effectively, if you visit the URL http://example.com/whoweare.aspx (which is the actual URL of the page), you'll be 301 redirected to the URL http://example.com/who-we-are (the virtual URL), and if you visit the virtual URL, you'll be rewritten to the actual URL.
This means super sexy URLs without duplication, and it doesn't result in reciprocal rewriting either, so smiles all round.
My question is this: could this be done more elegantly?
It's a little cumbersome having to write out two rules to ensure that one is redirected to the other, and the other is rewritten to the one. Is it possible to write one rule which will achieve the functionality of the above two?
Elegance is a subjective term, I guess there are a couple of ways that would be better, such as using Rewrite extensibility and implement fancy mapping logic, but by far the way I would recommend is using just 2 rules, one for Redirect and one for Rewrite, and with that just leverage Rewrite Maps that will make it a bit more readable (but still painful) to manage them, for example below you would now only need to maintain the maps and never have to deal with rules anymore:
<system.webServer>
<rewrite>
<rules>
<rule name="Rewrite From Pretty URL" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{URLsToRewrite:{REQUEST_URI}}" pattern="(.+)" />
</conditions>
<action type="Rewrite" url="{C:1}" appendQueryString="false" />
</rule>
<rule name="Redirect To Pretty URL" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{URLsToRedirect:{REQUEST_URI}}" pattern="(.+)" />
</conditions>
<action type="Redirect" url="{C:1}" appendQueryString="false" />
</rule>
</rules>
<rewriteMaps>
<rewriteMap name="URLsToRewrite">
<add key="/who-we-are" value="/whoweare.aspx" />
<add key="/what-we-do" value="/whatwedo.aspx" />
</rewriteMap>
<rewriteMap name="URLsToRedirect">
<add key="/whoweare.aspx" value="/who-we-are" />
<add key="/whatwedo.aspx" value="/what-we-do" />
</rewriteMap>
</rewriteMaps>
</rewrite>
</system.webServer>

Resources