Mobile Sites
Contents |
Getting Started
To get live ads in your mobile site you just need to:
- Follow the integration steps below
- Sign up at http://adfonic.com/sign-up
- Add your site to your Adfonic account http://adfonic.com/sites-and-apps/add-site-or-app
- You can now get your unique Ad Slot ID from the Ad Integration page and replace the test id in your code - it looks like 22222222-2222-2222-2222-222222222222
Script Tags
Use the following tag for browsers compatible with script tags such as WebKit (iOS, Android..)
<script src="http://adfonic.net/js/22222222-2222-2222-2222-222222222222"/>
Make sure you replace 22222222-2222-2222-2222-222222222222 with your Ad Slot ID.
To send additional parameters as part of the request, refer to the table below:
| Parameter name | Required? | Format | Description |
|---|---|---|---|
| s.test | No | 0|1 | Test mode (0=false, 1=true) |
| t.colorScheme | No | blue|green|orange|purple |red|yellow | The background color to use when serving enhanced text ads on high-end devices. This enables you to customize the look and feel of these ads to match your own design template. |
| t.constraints | No | name1=value1;name2=value2.. | Allows you to constrain the properties of the ads that will be returned. You can override the automatic size detection for a given device by setting this to (for example) “width=300;height=50”. |
| u.gender | No | m|f | The user’s gender (male or female), if known |
| u.dob | No | Number in format YYYYMMDD | The user’s date of birth, if known |
| u.age | No | Integer | The user’s age, if known (alternative to u.dob) |
| u.ageLow, u.ageHigh | No | Integers | The user’s age range, if known (alternative to u.dob) |
| p.tags | No | Keywords in lowercase, comma-separated | Additional tags to use when selecting an ad to display |
The example below shows a tag, 'tennis' passed as part of the request (make sure these are correctly HTTP encoded):
<script src="http://adfonic.net/js/22222222-2222-2222-2222-222222222222?p.tags=tennis"/>
The response should look something like:
document.write('
<!-- Banner image -->
<a href="http://adfonic.net/ct/22222222-2222-2222-2222-222222222222/db77d46c-517d-4bed-95e7-e5fbfe11b942">
<img border="0" alt="" src="http://as.adfonic.net/as/d517a146-fb8c-4362-85e1-340e7d04b877" width="300" height="50" />
</a>');
Standard Tags
Standard tags are another option for mobile sites where requests are from lower end handsets:
<a href="http://adfonic.net/sc/22222222-2222-2222-2222-222222222222?r.impid=[RANDOM_ID]&r.fallback=<FallbackURL>">
<img src="http://adfonic.net/si/22222222-2222-2222-2222-222222222222?r.impid=[RANDOM_ID]&r.fallback=<FallbackURL>&t.constraints=<Dimensions>"/>
</a>
Notes on parameters
| Parameter name | Format | Description |
| r.impid (both) | A large integer | This will be used as the ImpressionID (numbers in img and ct request MUST be the same) |
| r.fallback (static-img) | Any valid image URL, url-encoded | This image will be served in the "no ad" case |
| r.fallback (static-ct) | Any valid destination URL, url-encoded | This URL will be redirected to in the "no ad/no impression" case |
Remember to replace 22222222-2222-2222-2222-222222222222 with your Ad Slot ID.
Sample Code
The following ready-made code templates that can be cut and pasted for the following common server-side platforms:
PHP
This section is in 2 parts:
- Base code that needs to be included (save this as adfonic.php)
- Code to call the ad
Base PHP Code
<?php
/**
* NOTE: In order for tracking cookies to be set, the ads must be requested prior to any
* output going to the user
*
* Potential additional parameters:
* u.age - actual age
* u.ageLow and u.ageHigh - for age range
* u.lang - override language (default is 'en-us')
*/
class Adfonic {
static $adfonic_ad_base = 'http://adfonic.net/ad';
var $client_id;
function __construct($client_id=null){
if (isset($client_id)) {
$this->client_id = md5($client_id);
}
}
/**
* Primary interface. Pass the ad identifier, any extra targeting parameters and tags
* @param params - name value parameters for targeting, do not url encode
* @return Ad content to directly embed
*/
function get_ad_content($ad_id,$params=array(),$tags=array()){
$ad_url = $this->build_ad_url($ad_id,$params,$tags);
$ch = curl_init($ad_url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
$output = curl_exec($ch);
$info = curl_getinfo($ch);
$adcontent = '';
if ($output == false || $info['http_code'] != 200){
$adcontent = '<!-- no ad available, received response '. $info['http_code'] . '-->';
}
else {
parse_str($output, $rvals);
// handle "magic" quote escaping
if (get_magic_quotes_gpc()){
$rvals = array_map('stripslashes',$rvals);
}
// WARNING: This will only work if the output hasn't started going to the user
if (isset($rvals['trackingId'])){
setcookie('adfonic-tracking-id',$rvals['trackingId'],time() + (3600 * 24 * 365 * 2)); // 2 years
}
if (isset($rvals['error'])){
$adcontent = '<!-- no ad available, Adfonic error: ' . $rvals['error'] . '-->';
}
else {
$adcontent = $rvals['adContent'];
}
}
curl_close($ch);
return $adcontent;
}
/**
* Retrieve url for the given id and any extra parameters (tags, etc)
*
*/
function build_ad_url($ad_id,$params=array(),$tags=array()){
$ad_url = self::$adfonic_ad_base. "/$ad_id?";
// url params as key=value
$u_params = array();
// copy the user-supplied parameters
foreach ($params as $k=>$v){
$u_params[] = '$k='.urlencode($v);
}
// tracking id
$rid = $this->get_tracking_id();
if (isset($rid)) {
$u_params[]= 'r.id='.$this->get_tracking_id();
}
// user's ip address
$u_params[] = 'r.ip='.$this->get_ip();
// pass on all the http headers
foreach ($_SERVER as $k=>$v) {
if (substr(strtolower($k),0,5) == 'http_') {
$k = str_replace('_','-', strtolower(substr($k,5)));
if ($k != 'cookie') {
$u_params[] = 'h.'.$k.'='.urlencode($v);
}
}
}
if (! empty($tags)){
$u_params[] = "p.tags=".urlencode(join(",",$tags));
}
$query_string = join("&",$u_params);
$ad_url .= $query_string;
return $ad_url;
}
/**
* Extract tracking id from request/cookies
*
*/
function get_tracking_id(){
if (isset($_COOKIE['adfonic-tracking-id'])){
return $_COOKIE['adfonic-tracking-id'];
}
else {
return $this->client_id;
}
}
function get_ip(){
if (isset($_SERVER['HTTP_CLIENT_IP'])){
return $_SERVER['HTTP_CLIENT_IP'];
}
return $_SERVER['REMOTE_ADDR'];
}
}
?>
PHP Code to Call Ad
<?php
include_once('adfonic.php');
$adfonic = new Adfonic();
$ad_content = $adfonic->get_ad_content("22222222-2222-2222-2222-222222222222");
?>
<?=$ad_content?>
Remember to replace 22222222-2222-2222-2222-222222222222 with your Ad Slot ID
JSP with JAR file
Download this JAR file and ensure that it is properly installed in your web application server. Once installed you can copy and paste the generated code into any JSP page where you wish to have an ad appear.
<%@ page import="com.adfonic.*" %>
<!-- Adfonic ad slot: NOTE have removed the ad slot description e.g. banner v MPU -->
<%
AdfonicAdClient adClient = new AdfonicAdClient();
AdfonicAdRequest adRequest = new AdfonicAdRequest();
%>
<%= adClient.getAd(request,
response,
"22222222-2222-2222-2222-222222222222",
adRequest) %>
Remember to replace 22222222-2222-2222-2222-222222222222 with your Ad Slot ID
In the adfonic-client.jar file, the AdfonicAdRequest class contains convenience methods exposed as bean properties for getting and setting optional request parameters. These methods are as follows:
- isTestMode() / setTestMode(boolean) – corresponds to s.test
- getSiteUserID() / setSiteUserID(String) – corresponds to r.id
- getGender() / setGender(String) – corresponds to u.gender
- getDateOfBirth() / setDateOfBirth(Date) – corresponds to u.dob
- getAgeInYears() / setAgeInYears(int) – corresponds to u.age
- getAgeRangeLow() / setAgeRangeLow(int) – corresponds to u.ageLow
- getAgeRangeHigh() / setAgeRangeHigh(int) – corresponds to u.ageHigh
- getColorScheme() / setColorScheme(String) – corresponds to t.colorScheme
- getIpAddress() / setIpAddress(String) – corresponds to r.ip
- getTags() – returns a java.util.List of tags; to add a tag, use getTags().add(“tag”)
JSP Standalone
This is an all-in-one version of the code that would otherwise be split between the adfonic-client.jar file and the JSP page. Due to its size, it's not recommended unless you don't have the ability or desire to add the JAR file to your application. In that case, simply paste the entire contents of the sample code into your JSP where you would like the ad to be placed.
<%@ page import="java.io.*" %>
<%@ page import="java.net.*" %>
<%@ page import="java.text.SimpleDateFormat" %>
<%@ page import="java.util.*" %>
<%
//==========================================================================
// Adfonic Ad Request Setup. This process should be done once per page.
// You can pass the same parameter map to the "getAdfonicAd" method as
// many times as needed, i.e. if you would like to display multiple ads.
//==========================================================================
Map adfonicParams = new HashMap();
// Uncomment this to enable test mode
//adfonicParams.put("s.test", "1");
// If you have access to a Ad Slot ID, you should pass it in order to
// enable the most effective targeting possible
String yourUserID = null; // set this...
// Pass gender as "m" or "f" if known
//adfonicParams.put("u.gender", "m");
// Preferred method of passing age: pass date of birth as "YYYYMMDD"
SimpleDateFormat dobSdf = new SimpleDateFormat("yyyyMMdd");
//Date dateOfBirth = ...;
//adfonicParams.put("u.dob", dobSdf.format(dateOfBirth));
// Alternate method of passing age: pass the age value itself
//adfonicParams.put("u.age", String.valueOf(ageInYears));
// Another alternate method of passing age: pass an age range
//adfonicParams.put("u.ageLow", String.valueOf(ageRangeLow));
//adfonicParams.put("u.ageHigh", String.valueOf(ageRangeHigh));
// Optional language override
//adfonicParams.put("u.lang", "en-us");
// Additional tags to be used in union with tags pre-assigned to the ad space
List tags = new ArrayList();
//tags.add("sports");
//tags.add("football");
if (tags != null && !tags.isEmpty()) {
StringBuffer tagBuf = new StringBuffer();
for (Iterator tagIter = tags.iterator(); tagIter.hasNext(); ) {
String tag = (String)tagIter.next();
if (tagBuf.length() > 0) {
tagBuf.append(',');
}
tagBuf.append(tag.toLowerCase());
}
adfonicParams.put("p.tags", tagBuf.toString());
}
// Uncomment this to control the text ad color scheme, values of
// which may be: (grey|black|blue)
//adfonicParams.put("t.colorScheme", "grey");
if (yourUserID != null && !yourUserID.equals("")) {
// We'll pass an MD5 hash of your user ID for security
adfonicParams.put("r.id", md5(yourUserID));
}
else {
// Otherwise, we fall back on passing the Adfonic tracking ID
String trackingID = getAdfonicTrackingID(request);
if (trackingID != null) {
adfonicParams.put("r.id", trackingID);
}
}
// Pass the IP address
String ipAddress;
String forwardedIp = request.getHeader("X-Forwarded-For");
if (forwardedIp != null) {
// If it has been forwarded multiple times, there will be
// multiple IPs listed. We only want the last one...
int lastComma = forwardedIp.lastIndexOf(",");
if (lastComma >= 0) {
ipAddress = forwardedIp.substring(lastComma + 1).trim();
}
else {
ipAddress = forwardedIp;
}
}
else {
ipAddress = request.getRemoteAddr();
}
adfonicParams.put("r.ip", ipAddress);
// Pass all HTTP request headers as "h.*" parameters
Enumeration names = request.getHeaderNames();
while (names.hasMoreElements()) {
String name = (String)names.nextElement();
if ("Cookie".equalsIgnoreCase(name)) {
continue; // Don't forward cookies
}
else if ("Authorization".equalsIgnoreCase(name)) {
continue; // Don't forward Basic-Auth creds
}
String value = request.getHeader(name);
adfonicParams.put("h." + name.toLowerCase(), value);
}
%>
<!-- your HTML here -->
<%-- Fetch and include (inline) an Adfonic ad for a given AdSpace ID --%>
<%= getAdfonicAd(request,
response,
"137fc618-639a-486e-ab43-c95d0fb3b139",
adfonicParams) %>
<%!
/** Get embedded/inline ad content from Adfonic. You may call this method
as many times as needed per page in order to display multiple ads.
@param adSpaceID the ID of the publisher's ad space
@param params the targeting parameter map
*/
static String getAdfonicAd(HttpServletRequest request,
HttpServletResponse response,
String adSpaceID,
Map params)
{
StringBuffer buf = new StringBuffer();
buf.append("http://adfonic.net/ad/")
.append(adSpaceID)
.append("?");
boolean firstParam = true;
for (Iterator iter = params.keySet().iterator(); iter.hasNext(); ) {
String name = (String)iter.next();
String value = (String)params.get(name);
if (firstParam) {
firstParam = false;
}
else {
buf.append('&');
}
buf.append(name)
.append('=');
try {
buf.append(URLEncoder.encode(value, "utf-8"));
}
catch (UnsupportedEncodingException e) {
return "<!-- No ad available, exception caught: " +
e.getClass().getName() + ": " + e.getMessage() + " -->";
}
}
String url = buf.toString();
InputStream inputStream = null;
try {
HttpURLConnection conn =
(HttpURLConnection)new URL(url).openConnection();
// Uncomment the following lines in order to enforce timeouts
//conn.setConnectTimeout(10000);
//conn.setReadTimeout(30000);
conn.setAllowUserInteraction(false);
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.setDoOutput(false);
conn.setUseCaches(false);
conn.setInstanceFollowRedirects(false);
if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
// No ad available
return "<!-- No ad available, HTTP response code: " +
conn.getResponseCode() + " -->";
}
inputStream = conn.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[8192];
int numRead;
while ((numRead = inputStream.read(buffer)) > 0) {
baos.write(buffer, 0, numRead);
}
Map responseParams = decodeParams(baos.toString());
String trackingId = (String)responseParams.get("trackingId");
if (trackingId != null) {
// Cookie the user with the Adfonic tracking ID so that we can
// more effectively target them on subsequent requests
Cookie cookie = new Cookie("adfonic-tracking-id", trackingId);
cookie.setMaxAge(3600 * 24 * 365 * 2); // 2 years
response.addCookie(cookie);
}
String adContent = (String)responseParams.get("adContent");
if (adContent != null) {
return adContent;
}
String errorMessage = (String)responseParams.get("error");
return "<!-- No ad available, Adfonic error: " + errorMessage + "-->";
}
catch (java.io.IOException e) {
return "<!-- No ad available, exception caught: " +
e.getClass().getName() + ": " + e.getMessage() + " -->";
}
finally {
if (inputStream != null) {
try {
inputStream.close();
}
catch (java.io.IOException e) {
throw new RuntimeException(e);
}
}
}
}
static String getAdfonicTrackingID(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
for (int k = 0; cookies != null && k < cookies.length; ++k) {
if ("adfonic-tracking-id".equals(cookies[k].getName())) {
return cookies[k].getValue();
}
}
return null;
}
static Map decodeParams(String encoded) {
Map params = new HashMap();
StringTokenizer tokenizer = new StringTokenizer(encoded, "&");
while (tokenizer.hasMoreTokens()) {
String nvp = tokenizer.nextToken();
String[] toks = nvp.split("=");
if (toks.length == 2 && toks[1].length() > 0) {
try {
params.put(URLDecoder.decode(toks[0], "utf-8"),
URLDecoder.decode(toks[1], "utf-8"));
}
catch (java.io.UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
}
return params;
}
static String md5(String key) {
java.security.MessageDigest md;
try {
md = java.security.MessageDigest.getInstance("MD5");
}
catch (java.security.GeneralSecurityException e) {
throw new RuntimeException(e);
}
byte[] digest = md.digest(key.getBytes());
StringBuffer buf = new StringBuffer();
for (int k = 0; k < digest.length; ++k) {
buf.append(Integer.toHexString((digest[k] & 0xf0) >> 4));
buf.append(Integer.toHexString(digest[k] & 0x0f));
}
return buf.toString().toUpperCase();
}
%>