标题广告是Web上最常见的广告形式。本文介绍了一个基于IIS和ASP的标题广告管理系统,该系统支持广告客户和广告的管理,能够随机选择广告并生成显示广告的HTML代码(但参考广告的等级、显示次数限制、点击次数限制),并能够记录广告显示、点击的历史纪录。
一、数据库表结构
标题广告也就是Banner Ad,是Web上最常见的广告形式。本文介绍的标题广告管理系统利用Access数据库db.mdb来保存数据。db.mdb包含三个表:Advertisement保存有关广告的信息,Advertiser保存广告客户信息,BannerHistory保存广告显示和点击的历史记录。这三个表结构如下:
表 字段 类型 说明
Advertisment(广告) AdvertiserID 数字 广告客户的编号。
Status 数字 表示是否允许该广告显示。0表示不显示,1表示显示。当广告显示次数(或点击次数)超过显示次数限制值(或点击次数限制值)时,系统设置该值为0。也可以在广告管理功能内手工禁止广告显示。(在管理模块内,1显示为“可用”,0显示为“不可用”。)
ImageURL 文本 广告图片的URL,也就是图片的位置。
ImageWidth 数字 广告图片的宽度。
ImageHeight 数字 广告图片的高度。
Link 文本 广告客户所要求的广告链接。
AltText 文本 广告图片的文本。(用于<IMG>标记的alt属性)
Weight 数字 显示等级。等级值影响广告出现的频繁程度。本文实现预定义10个等级(1-10)。等级值越大广告出现的机会也越大。
StartDate 日期时间 开始日期
EndDate 日期时间 结束日期。在本实现中,这两个日期值并不影响广告的显示,只要已显示次数和点击次数没有超过限制值,广告总是可以显示的。
ViewLimit 数字 显示次数限制。广告显示次数超过该值时Status将变为0。
ClicksLimit 数字 点击次数限制。广告点击次数超过该值时Status将变为0。
AdID 数字 广告编号,由系统自动生成,是广告的唯一标识。AdID是本表的主键。
Impressions 数字 本广告已经显示的次数。
ClickThroughs 数字 本广告被点击的次数。
Advertiser(广告客户) Name 文本 客户名称
Address 文本 地址
CityStateZip 文本 城市和邮编
Phone 文本 电话
Fax 文本 传真
URL 文本 客户网站
Login 文本 客户通过Web查询自己的广告显示、点击情况时所使用的登录名称。
Password 文本 客户登录所用的密码。
EMail 文本 邮件。
AdvertiserID 数字 广告客户编号,由系统自动生成,是广告客户的唯一标识。AdvertiserID是本表的主键。
BannerHistory(显示或点击历史纪录) AdvertiserID 数字 广告客户编号。
AdID 数字 广告编号。
IPAddress 文本 浏览或点击广告者的IP地址。
Type 数字 Type表明本记录是显示广告还是点击广告。1表示显示,2表示点击。
datetime 日期时间 显示或点击广告的时间。
在本实现中,所有的处理逻辑均由ASP脚本实现,数据库仅用来保存数据,这是为了方便将系统从Access数据库移植到其他数据库。在实际应用场合,我们建议将部分处理逻辑在数据库中实现,例如比较现有显示次数和显示次数限制值以确定是否禁止广告显示(当然,这是在所使用的数据库系统支持该功能的前提下)。
从功能上来看,本文提供的系统可以分成两个部分:即管理部分和广告显示部分。管理部分用于增加、删除、修改广告、广告客户的有关信息,比如禁止或启用某个广告。显示部分负责生成显示标题广告的HTML代码。本文实现不提供有关显示、点击次数的统计图表,但这些数据都保存在BannerHistory表中,从该表可以方便地得到各种统计数据。有关ASP应用的图表制作,参见《利用ASP和HTML制作条形统计图表》。
二、管理功能
管理部分共有12个asp文件,这些脚本的主要功能分别如下:
BannerAdminLogin.asp:管理功能的登录页面。默认的用户名称是“ADMIN USER”,密码是“PASSWORD”。
CheckBannerAdministrationPassword.asp:检查使用管理功能的用户的密码。
NotLoggedIn.asp:“没有登录”提示页面,如果在登录之前访问管理页面,则显示该页面。
BannerAdministration.asp:这是管理功能的主界面,列出了所有的广告,并提供两个按钮。这两个按钮分别用于新增广告和新增广告客户。点击广告客户名字可以编辑该广告客户,点击广告文本可以编辑该广告。
Advertisement.asp:输入新广告的信息,或编辑当前广告信息,或调用DeleteAdvertisement.asp删除当前广告。
Advertiser.asp:输入新广告客户的信息,或编辑当前广告客户信息,或调用
DeleteAdvertiser.asp删除当前广告客户。
AddAdvertisement.asp:新增广告记录,从Advertisement.asp表单获取信息,存储到数据库。
AddAdvertiser.asp:新增广告客户记录,从Advertiser.asp表单获取信息,存储到数据库。
UpdateAdvertisement.asp:从Advertisement.asp表单获取信息,更新数据库中与当前广告具有相同AdvertisementID的记录。
UpdateAdvertiser.asp:获取Advertiser.asp表单信息,更新数据库中与当前广告客户具有相同AdvertiserID的记录。
DeleteAdvertisement.asp:根据当前选中广告的AdvertisementID,删除数据库中的相应记录。注意:删除并返回管理主界面后有时需要重新刷新。
DeleteAdvertiser.asp:根据当前选中广告客户的AdvertiserID,删除相应的数据库记录。
【图1】
完整代码请从本文后面下载。假设所有文件均在inetpubScripts目录下,则登录管理功能的URL为:http://localhost/scripts/BannerAdminLogin.asp。所有其他功能均可从此开始访问。
接下来我们介绍管理功能脚本中的一些关键问题。
㈠ 安全
大多数执行管理功能的页面受密码保护,这些页面在执行其任务之前都会检查一个SESSION变量以确认用户已经成功地登录。检查代码如下所示:
' 检查用户是否已经登录
If SESSION( "LoggedIn" ) <> true Then
Response.Redirect( "NotLoggedIn.asp" )
End If
这里所采用的安全机制较为简单,更多的说明参见《在ASP应用中验证用户身份》。
㈡ 列出所有的广告
BannerAdministration.asp页面启动时会列出数据库中的所有广告记录。这部分功能通过一个简单的查询和一个记录集对象完成,如下所示:
'列出数据库中的所有广告
Set cn = Server.CreateObject( "ADODB.Connection" )
cn.Open "BannerBuddy"
Set rs = Server.CreateObject( "ADODB.RECORDSET" )
Set rs2 = Server.CreateObject( "ADODB.RECORDSET" )
strSql = "SELECT * FROM Advertisement"
rs.Open strSql, cn
strCRLF = Chr( 13 ) + Chr( 10 )
While not rs.EOF and not rs.BOF
' 根据广告客户编号(AdvertiserID)查找客户名称
strSql = "SELECT Name From Advertiser where AdvertiserID = " + _
CStr( rs.Fields( "AdvertiserID" ) )
rs2.Open strSql, cn
strAdvertiser = ""
If not rs2.EOF and not rs2.BOF Then
strAdvertiser = rs2.Fields( "Name" )
End If
Response.Write( "</tr>" + strCRLF )
rs2.Close
rs.MoveNext
Wend
系统假定数据库db.mdb的ODBC DSN为BannerBuddy,因此在运行程序之前必需设置好这个DSN。有关数据库连接和操作的更多说明,参见《ASP应用中数据库记录的选取与过滤》。
在广告清单中,单击广告客户名字可以编辑该广告客户的信息,单击“文本/图形”栏中的文本可以编辑该广告的信息,单击图片链接可以查看图片。
㈢ 新增、修改广告和广告客户
AddAdvertisement.asp和AddAdvertiser.asp这两个脚本的任务是获取提交给它们的表单数据,创建广告客户或广告数据库记录。下面的代码用于新增广告记录,新增广告客户(AddAdvertiser.asp)的代码也类似,此处略。
' 连接到数据库,创建记录集对象rs,略...
strStartDate = Request.Form( "StartMonth" ) + "/" + _
Request.Form( "StartDay" ) + "/" + _
Request.Form( "Startyear" )
strEndDate = Request.Form( "EndMonth" ) + "/" + _
Request.Form( "EndDay" ) + "/" + _
Request.Form( "Endyear" )
nStatus = 1
If UCase( Request.Form( "Status" ) ) = "INACTIVE" Then
nStatus = 0
End If
' 根据所选择的广告客户名字,获取其编号
nAdvertiserID = 1
strSql = "select AdvertiserID from Advertiser where Name = '" + _
Request.Form( "Advertiser" ) + "'"
rs.Open strSql, cn
If not rs.EOF and not rs.BOF Then
nAdvertiserID = rs.Fields( "AdvertiserID" )
If IsNull( nAdvertiserID ) Then
nAdvertiserID = 1
End If
End If
' 生成一个新的广告编号
nAdvertisementID = 1
strSql = "select AdID=Max( AdID ) from Advertisement"
rs.Close
rs.Open strSql, cn
If not rs.EOF and not rs.BOF Then
nAdvertisementID = rs.Fields( "AdID" ) + 1
If IsNull( nAdvertisementID ) Then
nAdvertisementID = 1
End If
End If
' 插入新广告记录的SQL命令
strSql = "insert into Advertisement " + _
"( AdvertiserID, Status, ImageURL, " + _
"ImageWidth, ImageHeight, Link, " + _
"AltText, Weight, StartDate, EndDate, " + _
"ViewLimit, ClicksLimit, AdID ) Values ( "
strSql = strSql + CStr( nAdvertiserID ) + ", "
' 加上其他字段值,略...
strSql = strSql + CStr( nAdvertisementID ) + " )"
rs.Close
rs.Open strSql, cn
修改广告、广告客户信息分别由UpdateAdvertiser.asp和UpdateAdvertiser.asp完成,这两个脚本和AddAdvertisement.asp、AddAdvertiser.asp非常相似,只是把增加记录操作改成了修改记录。删除广告、广告客户的脚本很简单(分别为DeleteAdvertisement.asp和DeleteAdvertiser.asp),此处略。
三、显示广告
这部分程序主要有如下四个目的:第一,参考各个广告的显示等级,随机选择本次显示的广告;第二,更新数据库中该广告的显示次数;第三,输出标题广告的HTML代码;第四,在数据库历史表中保存显示和点击历史纪录。
实现上述功能的脚本主要有两个:
ShowBanner.asp:确定本次调用要显示的广告,更新显示次数记录,生成标题广告的HTML代码。
Redirect.asp:重定向页面。ShowBanner.asp生成的广告HTML代码将调用该脚本,由该脚本记录点击历史数据、重定向到广告客户指定的页面。
本文下载包中的ShowBanner.asp同时也是一个广告显示示例页面,每次刷新该页面可以显示出不同的广告。下面我们按照ShowBanner.asp的执行过程,介绍其中的关键步骤。
㈠ 计算显示等级总和
本系统采用的广告选择算法是:首先计算出当前所有可用广告的显示等级总和,然后根据这个和值生成一个随机数,再根据这个随机数来确定本次显示的广告。下面的代码用于计算可用广告的显示等级总和:
nTotalWeight = 0
strSql = "SELECT SUM( Weight ) As SumWeight FROM " + _
"Advertisement WHERE Status=1"
rs.Open strSql, cn
If not rs.EOF and not rs.BOF Then
nTotalWeight = rs.Fields( "SumWeight" )
' nTotalWeight有可能为空值
If IsNull( nTotalWeight ) Then
nTotalWeight = 1
End If
End If
在计算出nTotalWeight之后,我们可以根据该值生成一个随机数,如下所示:
Randomize
nRandomNumber = Int( Rnd * nTotalWeight ) + 1
程序将从数据库读取可用广告记录(参见下面的代码),累计已读取记录的weight总和,当这个新的总和超过这里生成的随机数时,就将当前记录作为本次显示的广告。
㈡ 分析可用广告记录
接下来的任务是执行一个查询,提取所有可用广告记录。如前所述,在遍历这些可用广告记录时,记录已读取记录的weight值总和nWeightCount ,当nWeightCount 等于或大于前面生成的随机数nRandomNumber时,程序就认为找到了本次要显示的广告。具体如下:
strSql = "SELECT * FROM Advertisement WHERE Status=1"
rs.Close
rs.Open strSql, cn
bDone = false
' 已读取记录的Weight值总和
nWeightCount = 0
' 清除变量
strImageURL = ""
strAltText = ""
strLink = ""
nImageWidth = 0
nImageHeight = 0
nWeight = 0
nAdID = 0
nAdvertiserID = 0
nViewLimit = 0
nImpressions = 0
While not rs.EOF and not rs.BOF and not bDone
' 将数据库值赋给变量
' 这种算法不利于效率,但简化了控制结构
strImageURL = rs.Fields( "ImageURL" )
strAltText = rs.Fields( "AltText" )
strLink = rs.Fields( "Link" )
nImageWidth = rs.Fields( "ImageWidth" )
nImageHeight = rs.Fields( "ImageHeight" )
nWeight = rs.Fields( "Weight" )
nAdID = rs.Fields( "AdID" )
nAdvertiserID = rs.Fields( "AdvertiserID" )
nViewLimit = rs.Fields( "ViewLimit" )
nImpressions = rs.Fields( "Impressions" )
nWeightCount = nWeightCount + nWeight
rs.MoveNext
' nWeightCount是否等于或大于随机变量值
If nWeightCount >= nRandomNumber or rs.EOF Then
bDone= true
End If
Wend
㈢ 更新当前广告的显示次数
在确定本次要显示的广告之后,程序就可以更新该广告记录的Impressions字段。如果新的Impressions值超过了显示次数限制(nViewLimit),还必需设置Status字段为0(即本广告不可再显示)。实现代码如下:
nStatus = 1
nImpressions = nImpressions + 1
If nImpressions >= nViewLimit Then
nStatus = 0
End If
strSql = "UPDATE Advertisement Set Status=" + _
CStr( nStatus ) + ", Impressions=" + _
CStr( nImpressions ) + " WHERE AdID=" + _
CStr( nAdID )
rs.Close
rs.Open strSql, cn
㈣ 生成HTML代码
在完成上述准备工作之后,接下来就可以输出显示广告的HTML代码。所输出的HTML代码可以分成如下几个部分:
重定向页面 --> 目标URL --> 其他参数 --> 图片标记
为什么不是直接链接到广告客户指定的URL呢?这是因此,虽然这种方法更简单,但我们希望能够记录广告的点击数量,在重定向页面中我们就可以更新该广告的ClickThroughs字段值。
在显示广告的HTML代码中,重定向页面本文假定为Redirect.asp,目标URL来自数据库,其他参数主要是广告编号、广告客户编号等,Redirect.asp利用这些参数记录点击历史纪录。具体实现如下:
strHtmlCode = _
"<a href=Redirect.asp?" + _
"Link=" + strLink + _
"&AdvertisementID=" + CStr( nAdID ) + _
"&AdvertiserID=" + CStr( nAdvertiserID ) + Chr( 34 ) + _
" target=newFrame><" + Chr( 13 ) + Chr( 10 ) + _
"></A>" + Chr( 13 ) + Chr( 10 )
这里的strHtmlCode即为显示广告的HTML代码。
㈤ 记录其他信息
为了给广告客户提供更多的信息,同时也为了便于进一步分析,除了记录显示次数之外,程序还在数据库表中记录其他一些信息(浏览本次广告时,浏览者所在的IP地址以及浏览时间、广告编号、广告客户编号),如下所示:
strSql = "INSERT INTO BannerHistory " + _
"(AdvertiserID, AdID, IPAddress, Type) Values (" + _
CStr( nAdvertiserID ) + ", " + _
CStr( nAdID ) + ", '" + _
Request.ServerVariables( "REMOTE_HOST" ) + _
"', 1)"
rs.Open strSql, cn
浏览的日期时间值在Access数据库内设置,即设置字段默认值为Now()。
㈥ 重定向页面
本文提供一个简单的重定向页面Redirect.asp,其功能是记录广告点击数量,然后生成历史表BannerHistory中的记录,最后重定向到目标URL,如下所示:
' 连接数据库,创建记录集对象rs,略...
' 增加广告的点击计数,如点击计数超过限制值,
' 则设置Status为0
strSql = "UPDATE Advertisement " + _
"Set ClickThroughs=ClickThroughs+1, " + _
"status=iif(ClickThroughs>=ClicksLimit,0,1) " + _
" WHERE AdID=" + Request.QueryString( "AdvertisementID" )
rs.Open strSql, cn
' 生成广告点击历史纪录
strSql = "INSERT INTO BannerHistory " + _
"(AdvertiserID, AdID, IPAddress, Type) Values (" + _
Request.QueryString( "AdvertiserID" ) + ", " + _
Request.QueryString( "AdvertisementID" ) + ", '" + _
Request.ServerVariables( "REMOTE_HOST" ) + "', 2)"
rs.Open strSql, cn
' 重定向到广告客户指定的页面
Response.Redirect( Request.QueryString( "Link" ) )
Next Steps
