WebAdverts is a comprehensive system for maintaining a set of rotating banner ads on your site or for setting up a “banner exchange” between your site and others. Banners can be displayed on your pages via JavaScript, IFRAME, IMG or SSI tags. (Banners may also easily be included on CGI-generated pages.) Multiple “zones” can be established, allowing certain banners to appear only on certain pages. WebAdverts keeps track of exposures and click-thrus for each banner, as well as of the average total number of exposures per day. Individual passwords allow each of your advertisers to view their own advert stats (overall and daily) without viewing anyone else’s. Banners can be “weighted” to control how often they are displayed, and can automatically be expired from the rotation after a designated number of exposures, click-thrus or days.


The files that you need are as follows:

ads.pl: This is the script you call directly, in order to display banners on your HTML pages.

ads_display.pl: The script which actually handles the banner displays. It is referenced by the ads.pl script; you don’t need to call it directly.

ads_admin.pl: The administrative maintenance script. With this script, you can add, edit and delete accounts. It also allows you (and your advertisers) to check on how well your accounts are performing.

ads_settings.pl: The configuration script containing the majority of the configuration variables used by both the administrative and the display scripts.

ads_rebuild.pl: This script is called when needed by the administrative script. You don’t need to call it directly or modify it in any way.

ads_text.pl: This script contains the text passages shown by the administrative script to your advertisers or exchange members. They are separated from the administrative script to make editing or translating easier. Note that this document does *not* include some of the text passages seen only by you, the administrator, and not by your advertisers or exchange members.

Setting up the script is quite easy. You’ll first need to set up a directory to contain your data files. Make sure, of course, that it is set world-writable (“chmod a+w “). You can put the scripts in that same directory, if you like, or in another directory; the latter is to be prefered, though, for security reasons discussed below. (On some servers, you’ll have no choice; it may be that your scripts *have* to be in your CGI-BIN directory, in which case your data files *must* be elsewhere, since storing data files in your CGI-BIN is a *very* bad idea.) Make sure that the first lines of your ads.pl and ads_admin.pl scripts point correctly to the location of Perl on your system, and be sure that both those scripts are set world-executable (“chmod a+x “). The other scripts do *not* have to be executable, nor do they need the line pointing to Perl’s location, since they won’t be called except from other scripts.

In the display config script (ads.pl, or whatever you’ve renamed it), define the following variables:

$ADVsettings_path: The full server path (not the URL) of your ads_settings.pl script.

$ADVdisplay_cgi: The URL (not the path) of your ads.pl script. If you are using multiple copies of the ads.pl (possibly to define a set of zones), each of those scripts should point this variable to itself.

$ADVadvertzone: The “zone” (category) of banners which should be shown when this script is called. Even if you’re using zones, it isn’t actually necessary to define this variable, since (unless you’re calling banners via SSI tags) the banner calls themselves can specify a zone. For more information on setting up and using zones, see the “zoning” section of the documentation, below.

In the admin script:

$ADVsettings_path: This variable is precisely the same as the variable defined in the ads.pl script, and should be defined in the same way.

$ADVtext_path: The full server path (not the URL) of your ads_text.pl script.

$ADVrebuild_path: The full server path (not the URL) of your ads_rebuild.pl script.

The bulk of the configuration variables are, of course, found in the ads_settings.pl script. The first set affect the actual display of banners:

$ADVdisplay_path: The full server path (not the URL) to your display script (ads_display.pl).

$ADVadverts_dir: The full server directory path (not the URL) to your adverts data directory. Note that this directory does not need to be — and in fact should *not* be — the same directory within which your scripts are contained. For security purposes, this directory should be password protected or (better yet) inaccessible to Web browsers. (You need to make sure that visitors can access your ads.pl script, of course, but nothing else needs to be directly accessible!)

$ADVUseLocking: Under most circumstances, this variable should be defined as 1. Set it to 0 only if, for whatever reason, your server doesn’t support the flock() command. (If this variable is set to 0, a semaphore-based file locking will be used instead of flock(); while it works reasonably well in most situations, it isn’t nearly as efficient.)

$ADVUseCookies: Cookies are only relevant when banners are called via IMG tags, which in general, will only be the case if no better option is available for a particular visitor. Even so, the number of IMG tag calls could be significant, so the efficiency of those calls should be considered. This variable determines whether browser-based “cookies” or a data file on your server will be used to keep track of which visitors have seen which banners. If you set it to 0, the script will not utilize cookies. That’s bad. Unless you have a *VERY* compelling reason to do so, you should *never* set $ADVUseCookies to 0. Using cookies is *much* more efficient than constantly updating and reading a file on your server. Turning off cookie support *will* result in a noticeable increase in the load on your Web server, especially if you’re running a busy site.

$ADVCheckForCookie: If you set this variable to 1, then the script, before displaying a banner and “blindly” setting a cookie, will set a “dummy” cookie in order to be sure that the visitor’s browser is actually set to utilize cookies. For those visitors who can’t or won’t utilize cookies, the script will “fall back” to storing data in a file on your server. Performing this check will result in a slight increase in the work your server is doing, though it still won’t be working as hard as if cookies are turned off. On the “up” side, though, use of this check will ensure that *all* of your visitors, whether they allow cookies or not, will be able to click on your banners successfully. (Without this check, the script will simply have to assume that cookies are being set, which means that visitors who can’t or won’t allow cookies will get error messages when they click on your banners.)

$GraphicTimestamp: If you set this variable to 1, the URL of each banner sent by the script will include a “timestamp.” (In other words, rather than appearing in the IMG tag simply as “banner.gif,” it might appear as “banner.gif?968429321″ instead.) This will *not* in any way affect the browsers’ ability to display the images; however, it *will* “fool” the browser into thinking that repeated displays of the same banner are actually displays of distinct banners, and thus force the browser *not* to reload the image from cache. Unless you have advertisers who want to be able to count “pulls” of their banner graphic for comparison to WebAdverts’ reported exposure count, though, you should probably leave this variable undefined, as it will just result in wasted bandwidth. (Note that WebAdverts’ count will likely be slightly higher than the “pull” count, in any event, since WebAdverts counts the number of times it sends an IMG tag to a page, and has no way of “uncounting” people who don’t load graphics and/or who use “banner-blocking” software.) If you want to include such timestamps in the URLs of only a few of your accounts, instead of setting this variable, you can simply add “” in the URLs, where you want WebAdverts to insert the timestamps.

$ADVLogIP: If you set this variable to 1, WebAdverts will maintain running log files of the IP addresses which have viewed or clicked on each banner. Keeping these logs allows account holders to keep an eye on how many different people are viewing their banners, and also allows the administrator to keep an eye out for exchange members or others attempting to “skew” their account stats by repeatedly loading or clicking on banners.

$ADVResolveIPs: If your server provides you only with raw IP addresses instead of with resolved domain names, you can set the script to resolve IP addresses for you. This will allow domain names rather than just IP addresses to be seen in the IP log files. However, if your site is even remotely active, utilizing this capability is *not* recommended, as in the final analysis, it’s a rather useless drain on system resources.

$DupViewTime: If you want to prevent multiple exposures of a single banner to a single visitor from counting against that banner’s total, set this variable to the minimum number of minutes which must elapse between counted views. For example, if you set it to 5, once a given visitor has seen a particular banner, further showings of that banner to that visitor will *not* be counted by the system until at least five minutes have elapsed. Normally, this variable should be left at 0, both for reasons of improved efficiency and because most of the time you won’t *want* to “undercount” your exposures. However, if you are running an exchange, and have problems with members trying to “inflate” their statistics, and don’t want to be bothered having to spot the abusers manually and put them on a permanent “ignore” list, this is the next-best solution.

$DupClickTime: This variable works exactly the same as the $DupViewTime variable, only it determines how many minutes must pass before a second click-thru (rather than a second exposure) will be counted by the system.

$ClickViewTime: This variable is yet another variation on the same theme, and determines how many minutes must pass after a visitor clicks on a banner, before another *exposure* to that visitor will be recorded.

$LogByZone: If you set this variable to 1, when you (or your account holders) view an account’s stats, you’ll be able to view a breakdown of how the banner is performing in each zone (or on each member’s site). The bookkeeping overhead isn’t too terrible, but if you’re running a very large exchange, the data files might start getting large, which could cause minor slowdowns.

$ADVRandomizeList: Setting this variable to 1 will instruct the script to “randomize” the order of the accounts in your rotation list every 12 hours. This can be handy, especially if you have advertisers with multiple accounts, as it will ensure that banners aren’t always seen in the same general sequence.

$DefaultBanner: You can, if you choose, define this variable with the name of one of your accounts. If you do so, that account’s banner will be displayed at any time when (for whatever reason) the system isn’t able to find an eligible banner via the normal routines. Note that this assignment is far more useful in banner exchanges than in straight advertising setups. Note also that if you’ve set up your accounts correctly, and have at least one account which is *always* eligible for display — in other words, if you’ve got at least one account set with a weight of 1, which is *not* dependent upon reciprocal displays to “earn” exposures — then this variable will never even be referenced. To be blunt, it exists solely as a “CYA” for administrators who don’t bother to set up their exchanges properly.

$ADVIgnoredIPs: You can enter a list of IP addresses or domain names (or portions thereof) in this variable, separated by spaces. Any visitor whose IP or domain matches an entry in this list will still be shown banners; however, the views or click-thrus will *not* be recorded by the script. This allows administrators to prevent their own activity on their Web sites from counting against their advertiser’s banner’s exposure counts, and also provides an easy way of dealing with exchange members who try to artificially inflate their exposure counts by repeatedly viewing their own pages.

$ADVRequireMember: If you set this variable to 1, any banner call that does *not* include a “member=” or “ID=” reference to a valid account will *not* be sent a banner. (This restriction does not, of course, apply when banners are called via SSI tags, since they can’t include such designations; however, since SSI tags can only be used from within the same domain which houses the script, exchange “cheaters” and others trying to skew your stats won’t have any way of taking advantage of them.)

$ADVIFRAMEbodyspec: Banners can be called via IFRAME tags, which act sort of as “windows” from the calling site to your server. This variable is very similar to the $bodyspec variable discussed below, and allows you to define a background color or image to match that of the site calling the banners, so that the “window” isn’t obvious while the banner is still loading.

$ADVIFRAMErefreshrate: Another advantage of IFRAME tags is that, since they’re actually showing banners on a page “behind” the one your visitors are viewing, the banners can be refreshed without affecting the rest of what your visitors are looking at. If this variable is set to anything other than 0, banners displayed through IFRAME tags will thusly refresh. The value of the variable is the number of seconds between new banner calls.

$ADVIFRAMEJSConflict: If you have a JavaScript banner call “nested” within an IFRAME banner call — so that the JavaScript call is used by browsers which don’t support IFRAME tags — certain versions of MS Internet Explorer will incorrectly process *both* banner calls. The obvious way to avoid this problem is not to nest JavaScript tags within IFRAME tags. (If you’ve set the script to use both for exchange member banner code, the IFRAME tag will be nested within the JavaScript tag.) However, if some pages calling banners use the incorrectly-handled nesting — for example, exchange members who still use code generated by an earlier version of WebAdverts, in which JavaScript tags were nested within IFRAME tags — then simply avoiding the problem might not be easy. If that’s the case, you can set this variable to 1, to instruct WebAdverts to check for and ignore the multiple banner calls generated by the faulty versions of MSIE. Don’t do this unless you need to, though, as it does increase the processing that must be done by the script.

$ADVJSConflict: JavaScript tags can show *almost* any sort of banner. However, in some cases, banners which themselves contain JavaScript code *can’t* be displayed via JavaScript tags. If this variable is set to 1, any banner containing code won’t be eligible for
display via JavaScript tags. If you set it to 0, the script won’t
enforce such a restriction. If you’re running JavaScript banners,
and want to try displaying them via JavaScript tags, set $JSConflict
to 0 and see what happens. If the banners *do* show up, you’re fine.
Otherwise, set the variable back to 1. Note that JavaScript tags
*will* still display “alternate” forms of JavaScript banners, if in
addition to defining the “raw mode” entry, you’ve also defined normal
banner and link URLs. As well, if you’re using the JavaScript tags
only as a backup to IFRAME tags (as described later), then only
visitors with browsers that don’t support IFRAME tags will be
affected by the restriction.

$ADVDBMType: This variable determines how the DBM (database) files used
by the script, will be accessed. Most users can leave it set to 0.
If the script can’t open the database file, though — and especially
if you receive “Inappropriate file type or format” errors — try
setting it to 1. This will replace the basic tie() command with a
version of the command specific to the DB_File module, which
produces the above error message. If all else fails, set $DBMType
to 2, and instead of tie() commands, the more generic (but less
efficient) dbmopen() commands will be used.

$ADVHourOffset: If you are in one time zone and your Web host is in
another, you can use this variable to adjust the times shown for
posts on your BBS. For example, if your server is located in the
Eastern time zone, but you’re in the Pacific time zone, set it to

The rest of the configuration variables affect the way the
administrative script functions:

$admin_cgi: The URL (not the path) of the admin script itself.

$nonssi_cgi: The URL (not the path) of the config script you want
referenced by “non-SSI” (JavaScript, IFRAME and IMG tag) banner
calls. More precisely, this is the URL of the script that exchange
members should reference when calling banners for display. If
you’ve set up more than one config script (as for multiple zones),
then this variable should point to the one you want referenced “by

@zones: This variable simply contains a list of the zones in use in
your rotation, as:

@zones = (‘ZoneOne’,'ZoneTwo’,'ZoneThree’);

The zones listed here will be available as selection choices when
editing an account, to determine in which zones the banner should
be shown, and in the case of an exchange member, *from* which
zones banners should be displayed. (Zones are discussed in detail
later in this document.)

$AdminDisplaySetup: If you leave this variable set to 0, the admin
display will simply show you all accounts. If you have a large number
of accounts, though, setting this variable to 1 will allow you to
select which accounts to view (expired, active, those in a particular
zone, those awaiting administrative approval, etc.) each time you
load the display. This can make the admin page much more manageable
with large banner exchanges, for example.

$AllowUserEdit: Setting this variable to 1 will allow banner exchange
members or advertisers to create new accounts or to edit (some of)
their own account information. Depending upon the setting of the
$RequireAdminApproval variable, new or edited accounts (with the
exception of those in which only the password was updated) may be
temporarily removed from active rotation.

$RequireAdminApproval: Setting this variable to 1 will require that
the administrator approve any account added or “self-edited” by an
exchange member. Setting it to 0 will allow everything to be part of
the live rotation immediately, without admin intervention. (The
latter is *not* recommended, for what should be obvious reasons.)

$LogAdminAccesses: If this variable is set to 1, a log file will be
maintained, showing the IP addresses of those accessing the admin
script to view or update account information. This log file can be
viewed directly from the main administrative screen.

$BannedIPs: This variable functions similarly to the $IgnoredIPs
list in the ads.pl script. Anyone whose IP address or domain matches
an entry in this list will be denied access to the administrative
functions. They won’t be able to view or edit any accounts.

$MasterIPLogDays: If you’ve set the script to maintain IP log files
for each account, your account holders will be able to view lists
of all the IP addresses which have viewed or clicked on their
banners “since yesterday morning.” You, as the administrator, have
a bit more flexibility. The “master IP access report” isn’t a full
list, but does list the IP addresses which have most frequently
shown up on the IP lists, and which thus might potentially be
worrisome. This variable determines how long the daily log files
are kept. Note that the longer you keep the log files, and the
more accounts you have, the longer it will take the script to
generate the master report.

$IPLog: The IP reports will normally only show IP addresses,
unless either your server automatically resolves IP addresses
into domain names, or you’ve set the display script to resolve
them for you. However, if you happen to also use my WebLog
script, you can set WebAdverts to reference its “resolved IPs”
database file, to list domain names wherever possible along with
IP addresses. Simply define $IPLog to point to the file maintained
by WebLog (and make sure both scripts are referencing the DBM file
in the same manner!)

$UserUploadDir: If and only if you’re allowing users to edit their own
account information, you may also allow them the ability to upload
banners directly to your server. If you wish to do so, this variable
should be defined with the path (not URL) of the directory in which
banners are to be stored. Note that if you require changes to be
approved by the administrator, then any upload of a new banner *will*
result in the account being put temporarily on hold.

$UserUploadURL: The URL of the directory assigned above.

$MaxBannerSize: The maximum size (in kilobytes) of banners. If you
set this to 20, for example, any attempt by a user to upload a banner
graphic larger than 20 kb will be automatically rejected.

$RequireUpload: If you allow exchange members to upload their banners
to your server, you can go one step further, and actually *require*
them to do so. If you set $RequireUpload to 1, then your members
will not have the option to simply define a URL for their graphics;
they’ll *have* to upload them. On the one hand, this means that you
will be utilizing (potentially) a lot more disk space and bandwidth;
on the other hand, it means you have complete control over the
banners appearing in your rotation.

$DefaultDisplayRatio: If you’re allowing users to edit their own data,
you’ll want to set this variable to the standard display ratio used in
your exchange.

$DefaultClicksRatio: This variable works just as does the one above,
only instead of defining how many displays earn one banner exposure,
it defines how many exposures are earned for a click. You can set
up your exchange so that your members earn exposures by displaying
other banners, and/or by generating clicks *on* those other bannners.

$ShowClicksFrom: If you want your exchange members to be able to see
how many click-thrus they’ve generated for the banners shown on their
sites, set this variable to 1. If you prefer that they *not* know
how many visitors are “leaving” their sites to visit other exchange
sites, leave it set to 0. Of course, if your exchange members *earn*
exposures for their own banners by generating click-thrus, then the
“clicks from” info will *always* be shown.

$DefaultWeight: The default weight for banner exchange member banners.
Normally, this should be left at 1.

$DefaultBorder: The default border width for banners displayed in your
rotation. (Each banner can have its own defined border width, of
course; this variable simply allows you to avoid having to type the
same entry over and over.) Note that if you’re utilizing IFRAME tags
in a banner exchange, you’ll probably want to leave IMG borders set
to 0. It’s easy enough to make the IFRAME window large enough to
display both the banner and its border, of course; however, the odds
of the border color you’ve defined for the IFRAME page looking good
on *all* of your members’ sites are rather slim. (For the same
reason, you should avoid getting fancy with the $IFRAMEbodyspec
definition when running an exchange.)

$NoBanners: If you’re running an “exchange” in which remote sites
display banners for you, but do *not* earn credits for or display
their own banners, set this variable to 1. New members signing up
will not be given any option to provide a URL or banner image, but
will still be provided with HTML code, assuming that you’ve defined
a display ratio for the account.

$IFRAMEexchange: If you set this variable to 0, the HTML code provided
to exchange members will include a simple IMG tag. This is fine if
everything being shown in your exchange is a simple GIF or JPEG
graphic. If you set this variable to 1, instead of IMG tags, the
HTML code will utilize IFRAME tags. This will allow a bit more
flexibility in what your advertisers or members can use as a banner.
Note that IFRAME tags are currently supported only by MS Internet
Explorer. Those using other browsers will still be able to see only
simple graphic files via IMG tags. But yes, the script is smart
enough not to send anything but a GIF or JPEG if an IMG tag is used,
so you can safely include both basic graphics and fancier “banners”
in your rotation. Note also that if you use IFRAME tags, you *must*
be sure to define TARGET attributes for all of your accounts’ banners
(which can easily be done with the $DefaultLinkAttribute variable),
as if you don’t, the banners’ destinations will appear in the same
frame in which the banners appeared. In other words, without a
TARGET attribute, your destination pages will appear *within* the
small spaces occupied by their banners! (In order to prevent
problems with MSIE browsers, which incorrectly cache CGI-generated
images, it is *strongly* recommended that you turn on at least one
of the $IFRAMEexchange and $JavaScriptExchange variables! Both can,
of course, be used together; when that’s done, JavaScript will be
the preferred display vehicle, followed by IFRAME, with IMG tag as
a “last-resort” backup.)

$JavaScriptExchange: If you set this variable to 1, instead of the
script including a basic IMG tag in the generated HTML code provided
to exchange members, it will include JavaScript tag (with an IMG tag
as a backup for those cases where JavaScript isn’t available.) Like
IFRAME and SSI tags, the JavaScript tag will allow (almost) any sort
of banner content — text, JavaScript, “rich media,” etc. — to be
displayed on your own or your members’ pages. (As was noted above,
though, some banners containing JavaScript code *can’t* be properly
displayed via JavaScript tags. But the script is able to work
around this problem, if $JSConflict is set.)

$ExchangeName: The name of your banner exchange. If supplied, this
will be used in the default HTML code supplied to exchange members
for use on their own pages.

$ExchangeURL: The URL of the “home page” for your exchange. This
should be the general information page that you want people to see
first. Like the name above, if supplied, it is used in the default
HTML code supplied to exchange members.

$ExchangeLogo, $ExchangeLogoWidth, $ExchangeLogoHeight: Optional image
URL and size designations for a graphic linked back to your exchange,
which can automatically be included next to exchange member banner

$ExchangeLogoPosition: The position the above exchange graphic. If
defined as “left” or “l” (or left undefined) the graphic will appear
to the left of the banners, as LinkExchange’s “button” graphics used
to. If defined as “bottom” or “b” the graphic will appear beneath
the banner, as does the new LinkExchange graphic. Other valid
definitions for this variable (as you would probably expect) are
“top” (or “t”) and “right” (or “r”).

$ExchangeBannerWidth & $ExchangeBannerHeight: If you require all
exchange members to use a specified banner size, you can define these
variables with the designated height and width to ensure that the size
attributes are included in the IMG tag in the HTML code supplied to
your exchange members.

$ExchangeBorder: The default border width around your exchange logo.
(This may or may not be the same as the border width around the
banners themselves.)

$DefaultLinkAttibute: The default “link attribute” (e.g.,
“TARGET=_top”) to be assigned to banners if called via SSI tags.

$bodyspec: Any attributes (BACKGROUND, BGCOLOR, TEXT, etc.) which
should be assigned to the tag on admin pages.

$fontspec: Any attributes (FACE, etc.) which should be assigned to
the fonts on your admin pages. These settings are used both in the
document as a whole and in individual table cells, since Netscape
Navigator isn’t smart enough to realize that document-wide settings
should be maintained in table cells unless specifically told so in
each and every cell….

$MetaFile: The path to a text file containing any HTML code (META tags,
etc.) to be inserted within the section of the pages produced
by the script.

$header_file and $footer_file: The full paths to optional text files
containing HTML code to be placed at the top and bottom of admin
pages. This allows you to include certain “standard” information
(links to exchange rules, for example) on all of the pages generated
by the script.

$admin_name: Your name (or, at least, that of the exchange’s
administrator). It will appear at the bottom of each admin page,
linked to your e-mail address, so advertisers or exchange members
can easily contact you.

$email_address: Your e-mail address. The “@” character in your address
must be “escaped” with a backslash (e.g., “scripts\@awsd.com”).

$mailprog: This variable defines what, if any, mail program is to
be utilized by the script. It can be defined in one of three ways.
The prefered definition is the absolute path to the “sendmail”
program, at least if you’re on a server that *has* it. (NT servers
do *not*.) Note that this is *not* the same as the “mail” program,
and has absolutely nothing to do with Matt Wright’s “formmail” or any
other CGI script. If your system doesn’t have “sendmail,” you can
instead define the variable as “SMTP” to instruct WebAdverts to access
your server’s mail server directly. Finally, if it’s available to
you, you can utilize Libnet’s “Net::SMTP” Perl module by defining the
$mailprog variable as “libnet”. Please note that the use of
WebAdverts’ e-mail functions is entirely optional; if you don’t want
to do so, simply leave this variable unassigned. The script’s e-mail
capabilities are: (a) the ability to send “welcome” or “reject”
messages to members when the administrator reviews their accounts,
(b) e-mail message to the administrator whenever a user joins or
updates his stats and thus requires new admin approval, (c) the
ability to e-mail account passwords to exchange members who have
forgotten them, and (d) the ability to send an e-mail message to
all (or a selected group) of your advertisers or exchange members.

$WEB_SERVER & $SMTP_SERVER: If you’re using a direct SMTP interface,
you can define either or both of these variables with the relevant
server names. If you leave them undefined, the script will attempt
to determine for itself what the names should be. If you’re using
sendmail, of course, these variables are irrelevant.

If you’re utilizing the direct SMTP interface rather than the
“sendmail” program, uncomment the “use Socket” line in the config file.
(In other words, remove the initial hash mark symbol.) Otherwise, just
leave it alone.

If you’re using the “Net:SMTP” module, uncomment the “use Net:SMTP”
line, the “use Socket” line, and also the relevant section of the
“SendMail” subroutine toward the bottom of the script.