永久链接,用于娱乐和利润






4.57/5 (9投票s)
永久链接提供了一种简单的方式来重定向传入流量到特定页面,跟踪点击和目标,以及防止外部链接过期。
引言
在为 CALM 构建 ASP.NET 网站时 [你注意到永久链接了吗?],我希望有一种简单的方法来了解哪些推荐链接正在为网站带来流量,哪些没有。我还希望有一种简单的方式根据来源的上下文来重定向传入流量,并跟踪不同的营销活动(来自文章、电子邮件、博客、Google AdWords 等)。永久链接解决了这三个问题。
目录
背景
永久链接的正式概念大约在 2000 年左右就已出现(参见 Wikipedia)。然而,任何曾经重新组织过网站、重命名页面、更改落地页或点击过已失效链接的人,可能都想象过这样的东西。
“Permalink”是“permanent link”(永久链接)的缩写。这个术语最初是用来引用已存档或已移动的网页或博客帖子的方式。永久链接通常与 URL 重写结合使用,这样浏览器就可以显示人类可读的(并且对搜索引擎友好的)URL,而后端仍然使用数据库跟踪链接。
实现
永久链接最简单的实现方式就是将一个 ID 号通过 URL 的查询字符串传递。主页面使用这个 ID 来决定显示哪个内部页面。
永久链接,带来乐趣
永久链接允许您在不更改网站的情况下更改落地页,只需更改链接 ID 在数据库中的目标条目即可。这使您可以在不冒着破坏外部链接的风险的情况下,根据需要重组您的网站。
永久链接,带来收益
永久链接允许您跟踪哪些推荐链接能够到达您的“目标页面”,无论是演示下载、订单,还是彩蛋。例如,主页面可以记住传入的链接 ID(例如,存储在 session 中),然后目标页面可以检索它并更新计数器来跟踪点击次数。
永久链接演示代码
演示应用程序包含一个 SQL 脚本,用于创建和填充一个小数据库,以及一个 ASP.NET 网站来演示永久链接的使用和跟踪。SQL 脚本创建了 Campaign 和 CampaignLink 表,并用一些示例数据填充它们。该网站包含几个内容页面和“目标”页面,以及一个“外部推荐”页面,用于模拟外部链接并演示如何非常具体地使用永久链接来跟踪推荐。还包含一个统计页面,用于显示每个 Campaign 和 CampaignLink 的点击和目标统计信息。
Using the Code
要运行演示,请使用具有创建数据库、表和存储过程权限的登录名打开 Microsoft SQL Server Management Studio。然后,打开脚本 create-permalinks-database.sql 并执行它。刷新“数据库”列表,您应该会看到 PermaLinks 数据库。
然后,在 Visual Studio 中打开 PermaLinkDemo.sln 文件(VS2005,一个主页),如果需要,请在 web.config 文件中更改连接字符串,然后构建并运行网站。默认页面是 external.aspx,它使用数据库中的 CampaignLinks 表来模拟外部链接。点击外部链接,查看它将您带到哪个页面。点击“目标”按钮来增加计数器。点击“返回”链接返回到外部链接页面。重复操作一段时间以提高计数。然后,点击“显示永久链接统计信息”链接查看结果。
关注点
网站和存储过程中使用的技术都很简单,但其中一些可能对某些人有益。
- 外部链接页面(external.aspx)是使用
SqlDataReader
和StringBuilder
来填充Literal
控件的链接表生成的。
protected void Page_Load(object sender, EventArgs e)
{
//we want to generate a full URL,
//e.g. https:///PermaLinks/?linkid=###
//this is probably not the best way to do this,
//but it works ;-)
string baseUrl = this.Request.Url.AbsoluteUri;
baseUrl = baseUrl.Replace("/external.aspx",
"/?linkid=");
//generate a table of links using a data reader;
//we could have used a repeater control instead
SqlConnection conn = null;
SqlCommand cmd = null;
SqlDataReader rdr = null;
StringBuilder sb = new StringBuilder();
try
{
conn = new SqlConnection(
ConfigurationManager.ConnectionStrings["db"].ConnectionString);
cmd = new SqlCommand("select CampaignLinkId,
CampaignLinkDescription from dbo.CampaignLink", conn);
conn.Open();
rdr = cmd.ExecuteReader(CommandBehavior.Default);
sb.Append("<table border='0' align='center' width='90%'>");
while (rdr.Read())
{
//generate a row in the table for each external link
sb.Append("<tr><td>>a href='");
sb.Append(baseUrl);
sb.Append(rdr.GetInt32(0)); //link id
sb.Append("'>");
sb.Append(rdr.GetString(1)); //campaign link description
sb.Append("</a></td></tr>");
}
sb.Append("</table>");
this.Literal1.Text = sb.ToString();
}
catch(Exception ex)
{
this.Literal1.Text = "ERROR: " + ex.Message;
}
finally
{
if (rdr != null && !rdr.IsClosed)
{
rdr.Close();
rdr.Dispose();
rdr = null;
}
if (conn != null && conn.State != ConnectionState.Closed)
{
conn.Close();
conn.Dispose();
conn = null;
}
}
}
protected void Page_Load(object sender, EventArgs e)
{
int linkId = 0; //default to first permalink if no linkid found
if (!int.TryParse(this.Request.Params["linkid"], out linkId))
{
linkId = 1; //default to first link
}
//find page to redirect to
string url = getUrl(linkId);
this.Session["linkid"] = linkId;
this.Response.Redirect(url);
}
protected string getUrl(int id)
{
SqlConnection conn;
SqlCommand cmd;
string url = "hireme.aspx";
try
{
conn = new SqlConnection(
ConfigurationManager.ConnectionStrings["db"].ConnectionString);
cmd = new SqlCommand("dbo.uspGetLinkUrl "
+ id.ToString(), conn);
conn.Open();
object result = cmd.ExecuteScalar();
if (result != null && result != DBNull.Value)
{
url = Convert.ToString(result);
}
}
catch
{
//just send to default page
}
return url;
}
protected void Button1_Click(object sender, EventArgs e)
{
//update buy counter
updateBuyCounter();
}
private void updateBuyCounter()
{
SqlConnection conn = null;
SqlCommand cmd = null;
string linkid = Convert.ToString(this.Session["linkid"]);
if (linkid == null || linkid.Length <= 0) { return; }
try
{
conn = new SqlConnection(
ConfigurationManager.ConnectionStrings["db"].ConnectionString);
cmd = new SqlCommand("exec dbo.uspUpdateBuyCount "
+ linkid, conn);
conn.Open();
cmd.ExecuteNonQuery();
}
catch
{
//in a real system, only catch SQL errors
}
finally
{
if (conn != null && conn.State != ConnectionState.Closed)
{
conn.Close();
conn.Dispose();
conn = null;
}
}
}
DataGridView
控件、一个 SqlDataReader
和一个返回三个结果集的存储过程生成的。protected void Page_Load(object sender, EventArgs e)
{
SqlConnection conn = null;
SqlCommand cmd = null;
SqlDataReader rdr = null;
try
{
conn = new SqlConnection(
ConfigurationManager.ConnectionStrings["db"].ConnectionString);
cmd = new SqlCommand("dbo.uspCampaignStats", conn);
cmd.CommandType = CommandType.StoredProcedure;
conn.Open();
rdr = cmd.ExecuteReader(CommandBehavior.Default);
GridViewCampaign.DataSource = rdr;
GridViewCampaign.DataBind();
rdr.NextResult();
GridViewCampaignLink.DataSource = rdr;
GridViewCampaignLink.DataBind();
rdr.NextResult();
GridViewTotals.DataSource = rdr;
GridViewTotals.DataBind();
}
catch
{
//in a real system, only catch SQL errors
}
finally
{
if (rdr != null && !rdr.IsClosed)
{
rdr.Close();
rdr.Dispose();
rdr = null;
}
if (conn != null && conn.State != ConnectionState.Closed)
{
conn.Close();
conn.Dispose();
conn = null;
}
}
}
结论
永久链接是一种简单的方法,可以防止“链接腐烂”,跟踪推荐,并监控流量。在网站的日志中可以找到更多详细信息,并且有几种产品可以解析这些日志并生成包含图表、路径等的详细报告。这些工具并非总是可用或方便;但是,简单的统计页面可以格式化成可以在智能手机上阅读,从而随时随地访问。
未来的增强
基本的永久链接实现可以通过会话 ID 来扩展,以跟踪访问者路径。永久链接也可以使用 HttpModule 来实现,但基本功能保持不变。永久链接还可以与 URL 重写结合使用,以创建更用户友好的链接,从而有效地隐藏浏览器或搜索引擎的链接 ID。最后,一个成熟的永久链接解决方案显然会包含管理页面来维护 Campaigns 和 CampaignLinks。
历史
- 2008-09-04
- 首次发布文章。