Archive for the ‘PHP Automation Coding’ Category

PHP Code to Check if Someone is Coming from a Open Proxy.

Wednesday, June 11th, 2008

php open proxy check

As some of you know I’ve been moving to building my own offers and some other things on the advertisers side I’ll sharing later. In this quest I’ve found the most challenging thing is to flush out the fraud from the legitimate users. Everyone thinks being an advertiser is the way to go right? Affiliates send traffic and you pay them 5$ and you make 7-10$. Well if only it was that easy. Honestly being the advertiser or network would be the greatest thing since sliced bread if there wasn’t so much affiliate fraud. Now I’m not talking about Blackhat tactics or spam traffic generation stuff. I’m talking straight fraud such as stolen credit cards and lead stuffing. There’s large organized rings of fraudsters primarily in China, India, Phillipines, Vietnam, Russia, Turkey and a few other countries. So if any of my readers on from those countries and get denied for networks and offers a lot that’s why.

Why you should care

Fortunately most of the fraudsters aren’t that sophisticated from what I’ve seen, so there’s a lot of ways to flush them out of the bushes and cut your losses before they start. There’s very good reason to catch them “Before” they start. As an advertiser the last thing you want is a large number of charge backs or stolen credit cards running through your system. If enough of this happens you can be blacklisted for any merchant account. Therefore the prevention of these transactions going through is a good place to begin.

One of the hard parts about owning a network or running an offer is the careful balancing act between what you let through and what you block. You could lock down your affiliate approval or purchase system tighter then a drum and approve hardly anyone. Or you could let everyone through but these are extremes of the spectrum of course. So the goal is to build little checks in to weed out most of the fraud before it starts. One thing I’ve chosen is anyone signing up with a proxy is going to get denied. If you can’t signup with your real IP I don’t want to do business with you. Maybe I’m going to knock out some sales and some affiliates this way but it’s worth it so I don’t have to deal with as much fraud.

Now there’s no way you can block all proxies, I know this but you can weed out the simple ones by checking the regular open proxy ports which are 80, 8080, and 3128. I’ve written a little function that you pass the IP address to and return 0 or 1 based on whether those ports are open on the IP. So that when an affiliate applies or a sale goes through I check if the IP ( address of the computer) is coming from computer that has those ports open. 99.9 out of a 100 home users aren’t going to have any of those ports open.

Just take this code and stick it in your sign up form or registration form and decide how you want to deal with these orders or sign ups. You may want to just throw them into a queue to be manually checked. Or build a rating system based on points. How you handle things is up to you.

PHP Proxy Port Checking Code:

function ipProxyPortCheck($ip){
//timeout you want to use to test
$timeout = 5;
// ports we're going to check
$ports = array(80,3128,8080);
// flag to be returned 0 means safe, 1 means open and unsafe
$flag = 0;
// loop through each of the ports we're checking
foreach($ports as $port){
// this is the code that does the actual checking for the port
@$fp = fsockopen($ip,$port,$errno,$errstr,$timeout);
// test if something was returned, ie the port is open
if(!empty($fp)){
// we know the set the flag
$flag = 1;
// close our connection to the IP
fclose($fp);
}
}
// send our flag back to the calling code
return $flag;
}
// call our function and check the IP in there
echo ipProxyPortCheck('69.217.73.52');
?>

Hope this saves some advertisers and affiliate networks some time and money.

PHP & CURL Forum

Tuesday, May 13th, 2008

Just a quick post about a forum I found today. If you’re looking for other people to talk about CURL and PHP with I came across this forum the other yesterday. Doesn’t seem super active however there might be some answers to your questions in the history.

http://curl.phptrack.com/forum/viewforum.php?f=1

Lots Of Proxies from 1 Server using 3Proxy

Tuesday, May 13th, 2008

My goal was to get 8k IP’s setup on a single server I’d never done this before but someone mentioned you could so I figured it was possible.

As mentioned in the title the proxy server we’re going to use is a Russian server called 3proxy. The beauty of 3proxy is it’s ultra lightweight, fast and you can run multiple IP’s in a single daemon because it has internal threads. Check out http://3proxy.ru/ which is the home of 3proxy.

We started off by getting all the IP’s pointed to the beefy dedicated server and then started playing with proxy software. We first started off with tinyproxy without much success. I had never used this before but my hosting company suggested and mentioned it would work for this setup. Unfortunately when you try to load 8k IP’s it starts a new daemon process in the OS for each IP and will eventually crash.

Next we moved to my old standby I’ve been using for a few years now, 3proxy which we tried the same thing as we did with tinyproxy which was start a daemon for each individual IP. We tried this first as this is how I have all my other servers configured and thought 3proxy might have a smaller footprint. Guess what? This crashed just the same. The next config was throwing 8k IP’s in a single daemon. CRASH! After that we gave 4 daemon’s, 2k per a shot. This actually ran but excrutiatingly slow. The load times of pages was 10x’s what it was running a single c-block and single daemon which was our base test case. What was interesting was the server was very responsive with a super low load using this setup, but for some reason the proxies were very unresponsive. I don’t know much about the internal coding of 3proxy but I imagine it has something to do with how it’s designed internally. Lastly I decided I’d try running an individual daemon for each c-block all at the same time. Now, for each daemon we need to run it on a different listening port. This was the magic bullet, seems if you don’t put to many IP’s in a single daemon they run smooth. As of right now I’m running about a 8 server load which high but things are still running very smoothly and the load times are almost as fast as not using a proxy at all.

If you want to run a lot of proxies on single server I ‘d suggest 3proxy which is a nice free opensource piece of software. Then run no more then 255 IP’s per daemon. The number of daemon’s per server you’re going to be able to run is solely dependent on how good the server is.

P.S. That fellow who told me I could run them all on the the same server later said no you couldn’t after the first couple of attempts. Also mentioned he’d never done it before.

If you’re interested in running a setup like this here’s a couple things to help.

1. This first script is going to make your config files for your daemons that 3proxy needs to run. These config’s are set as open proxies right and you should put some IP whitelisting or login/password protection on them. Read more on the 3proxy website about how to do this.

<?
// this is the port we'll start incrementing from
$port = 22406;
// first class C
$beginningclassc = 122;
//last class C
$endingclassc = 224;
//this is our class C id's like this XXX.XXX.122
for($c = $beginningclassc;$c <= $endingclassc;$c++)
{
// these are our settings for our config file
$filecontents = "#!/usr/local/bin/3proxy
nserver 127.0.0.1
nscache 65536
timeouts 1 5 30 60 180 1800 15 60
log /usr/home/3proxy.log
daemon
#auth iponly
auth none
dnspr
flush
auth none
";
// adding each of the IP's to the config file
for($i=2;$i<255;$i++)
{
$filecontents .= "external 111.222.$c.$i\n";
$filecontents .= "internal 111.222.$c.$i\n";
//
$filecontents .= "proxy -a -n -p$port\n";
}
// increments the port for the next loop
$port++;
// saves the file to a dir of your choosing with a filename
// that has the C segment in it for identification
file_put_contents("c:/files/proxy-$c.cfg",$filecontents);
}
?>


2. This second script is a bash script that runs on your server that will start each of the daemons. Instead of running
>3proxy proxy-112.cfg
all you have to do is run this script on your server and it’ll start them all for you.

#!/bin/bash
COUNTER=122
while [ $COUNTER -lt 224 ]; do
3proxy /root/3proxy/proxy-$COUNTER.cfg
let COUNTER=COUNTER+1
done

If you don’t know how to use this make a file on your server called “proxy-start”. Then chmod it 777 by the command chmod 777 proxy-start. Then just run it using ./proxy-start. That should get all your blocks up and running. If you have an issue you can just do a killall -9 3proxy which will kill all your 3proxy processes and you can start again.

Hope this helps someone :)

Curl Cookies – Quick Tip

Saturday, April 19th, 2008

I know I haven’t got around to writing script that uses cookies to login. However if you’re on that path and are interested in using cookies to do things like login and stay logged into a site there’s one troubling thing I had big issues with when I started.

To use a cookie we need to set it’s location and this is where I’ve had troubles. For some reason I’ve had problems using a cookie not set with the full path. So when you set your cookie location make sure you use the full path of your cookie location.

$cookie = “/home/user/tmp/cookie.txt”;
If you’re going to use multiple threads or want to code up a captcha solve you have to save the session so you probably want to do a
$cookie = “/home/user/tmp/cookie-”.rand(111,9999).”.txt”;

And that’s the quick tip. I beat my head against the wall with this one a bunch of times and the full path seemed to be the thing that solved the curl cookie issues I had. If you’re having problems with cookies give this a try.

Just quickly to use cookies you just use a couple of simple lines.

So the initial call you need to set a cookie like this

curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie); // sets the cookie file location
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie); // this says to start a new cookie file.

And that’s it to set the cookie on login or whatever you might need to start a cookie for. Then all your calls after that would look like this.

curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie); // sets the cookie file location
curl_setopt($ch, CURLOPT_COOKIE, $cookie); // use the cookie we have on file

And there you have it cookies are just that easy. I’ll get some example code up in the next day or so to show them in the wild.

PHP Platform I Write Code In

Thursday, April 3rd, 2008

As I’m sure you know PHP as with most languages you can code right in a text editor on your home computer. However this might not be the most effective use of your time. I get asked a lot, what I use to code in. Well after trying quite a few things the ZEND IDE is about the best thing I’ve found out there. Now I know there’s some of you that are going to whine that it’s a little overhead intensive and yes you’re right. Zend is by no means notepad. However it brings a lot of tools to the table that make it well worth that over head in my opinion.

  1. Built in sFTP, FTP drive mapping
  2. Stepped debugging
  3. Robust code completion library
  4. Version control and management

Now if you’re going to use Zend I invite you to go to tools/preferences first thing and uncheck “Use OS look and feel”. What this does is it makes Zend try and emulate what the rest of your computer looks like. For example if you’re running XP like me it gives it the XP look and feel. Honestly I hear a lot that Zend is super slow and people just can’t put up with it. Well this is what makes it slow, turn this off and the performance will improve 10 fold.

1. sFTP/FTP Drive Mapping
What got me started on writing this post is I was at nickycakes blog today and he was talking about drive mapping. I’m sure if you’re just starting or when you started with all this PHP and servers stuff one of the biggest pain in the butt’s was figuring out how this all worked. When I first started I used to run a copy of WAMP on my local machine and code everything locally. Then when I finished it and got it working I migrated it to the server. If you’ve ever done this you know the headache this can be. Windows has a totally different file structure. Permissions can be a pain in the ass and so on. Also once you have it on the server it’s going to require some debugging ( funny how software writing works that way ). So when I first started I’d download the file, edit it, upload it and test. As you can see doing this 100 times can be an arduous task.

Zend to the rescue. With zend you have a file manager in your left pane by default. In this pane all you have to do is left click then hit “add FTP server”. A window will pop up that will ask you the details of you FTP or sFTP connection. Then once you hit ok it’ll connect to the server and map a drive into Zend just like another hard drive on your local box. You can open, edit, close files all in real time which totally eliminates the upload/download task. This also allows you to build in real time on the server where the scripts are going to reside in the end. One thing to take note of. If you’re used to coding locally and uploading you always have a sort of backup of a working version online. Now that you’re controlling things in real-time you can easily write over something that works with something that doesn’t. Remember when you hit save the old file is gone.

2. Stepped Debugging
When I first shifted to PHP I came from a small background in Visual Basic and developing in Visual Studio. Well visual studio has very very robust debugging tools. For example if ( this is for php only coders ) you could hit run and it would go through your script step by step. Then as it’s going through you could mouse over each variable, object, array or whatever to see what was contained in it on that line. You can then make some tweaks and run that same line again and see if it fixed it. Something like this might be useful right? Well Zend has debugging built into it. And you can set it up so that it works direct on your server.

3. Robust Code Completion Library
This was HUGE when I was new and didn’t know many of the functions at all. Code completion allows you to start writing a function and it will bring up a list of functions to finish it. For example let say you’re looking for a string function to do something. Well you know that most of the string functions start with a “str” so you start typing that and it pops up the whole list of functions that start with “str” then you page down the list and find the one you’re looking for. When you type the complete function it shows you 1. a description of what the function does, 2. what the function takes as inputs and 3. what the functions generates as an output. This can be extremely helpful and save you a lot of time from going to php.net. Zend also has a powerful real-time syntactic code check. Just like when you’re working on a word document and it underlines grammar mistakes in real-time so does Zend with your syntax. It’s very useful to see if you missed a bracket here or there which you might spend a good amount of time debugging.

4. Version control management
If you’re working with a team on a single project and sharing files this can be really useful. Also is very helpful if you want to make backups along the way in an easy fashion. Zend supports both CVS and SVN. I’m not going to get into a lot chat about versioning. But just know it supports all the features of versioning natively.

5. I’m sure there’s other things I’m not thinking of right now.
If you’re reading this and use the Zend IDE feel free to add them in the comments.

That’s just a few reason to give Zend a shot. I can guarantee you with the tools it provides it will help you learn faster and speed your coding up. Don’t be lame and try it for a day or two. Really give it a shot as it’s a complex program that takes some getting used to. But will save you time and improve your coding once you d.

Pinging tool to let the world know your blog/site has been updated.

Thursday, March 13th, 2008

Are you familiar with what pinging an aggregator is? If you’re looking for a way to let the world know that your blog or website has been updated there’s something you can do which is called pinging an aggregator ( I’m sure there’s some technical term for it but I don’t know or care what it is. ) which is a website that collects the latest updates on site by notification. Some examples of these places are weblogs.com, technorati, feed burner, etc. Back in the day (sounding like an old man) you could ping these places and the spiders would come running and index you instantly, this was back in 2006. They’re not nearly as effective now but definately still bring the spiders. I’ve been asked numerous times if I would post a script to post to these engines and honestly the easiest way to do it is go through something like pingomatic.com. Which submits the pings to all the engines for you. I may later make a script that uses the xml post to a list of aggregators seperately. But for now to keep it easy lets get started with a simple pinger for pingomatic. This is an EXTREMELY simple script that if you know how to use curl you could do very easily. However sometimes the hard part is finding out what to post where. Therefore I’m going to touch on using LiveHTTPHeaders to pull the string out.

If you don’t have LiveHTTPHeaders please go to http://livehttpheaders.mozdev.org/ and install it now. I’m also going to assume you’re using FireFox as any self respecting dev should be. The first thing once you have LHH installed is go to “Tools” in firefox and then down to “Live Http Headers” and open the headers window. Next go to http://www.pingomatic.com in firefox. You’ll probably see a bunch of stuff fly by on the window as that’s the headers being passed and received to get to that page. Now you’ll want to hit clear and clean that out so the box is blank for LHH. Next fill in your values on the form on pingomatic.com, once you’re done hit “send pings”. Again you’ll see some info in the headers box that looks like this.

http://pingomatic.com/ping/?title=Oooff.com&blogurl=http%3A%2F%2Foooff.com%2Fphp-affiliate-seo-blog%2F&rssurl=http%3A%2F%2Foooff.com%2Fphp-affiliate-seo-blog%2Ffeed&chk_weblogscom=on&chk_blogs=on&chk_technorati=on&chk_feedburner=on&chk_syndic8=on&chk_newsgator=on&chk_myyahoo=on&chk_pubsubcom=on&chk_blogdigger=on&chk_blogstreet=on&chk_moreover=on&chk_weblogalot=on&chk_icerocket=on&chk_newsisfree=on&chk_topicexchange=on

GET /ping/?title=Oooff.com&blogurl=http%3A%2F%2Foooff.com%2Fphp-affiliate-seo-blog%2F&rssurl=http%3A%2F%2Foooff.com%2Fphp-affiliate-seo-blog%2Ffeed&chk_weblogscom=on&chk_blogs=on&chk_technorati=on&chk_feedburner=on&chk_syndic8=on&chk_newsgator=on&chk_myyahoo=on&chk_pubsubcom=on&chk_blogdigger=on&chk_blogstreet=on&chk_moreover=on&chk_weblogalot=on&chk_icerocket=on&chk_newsisfree=on&chk_topicexchange=on HTTP/1.1
Host: pingomatic.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.12) Gecko/20080201 Firefox/2.0.0.12
Accept: application/x-shockwave-flash,text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://pingomatic.com/
Cookie: blogurl=http%3A%2F%2Foooff.com%2Fphp-affiliate-seo-blog%2F; title=Oooff.com; pinged=a%3A13%3A%7Bi%3A0%3Bs%3A14%3A%22chk_weblogscom%22%3Bi%3A1%3Bs%3A9%3A%22chk_blogs%22%3Bi%3A2%3Bs%3A14%3A%22chk_technorati%22%3Bi%3A3%3Bs%3A11%3A%22chk_myyahoo%22%3Bi%3A4%3Bs%3A13%3A%22chk_pubsubcom%22%3Bi%3A5%3Bs%3A14%3A%22chk_blogstreet%22%3Bi%3A6%3Bs%3A14%3A%22chk_feedburner%22%3Bi%3A7%3Bs%3A11%3A%22chk_syndic8%22%3Bi%3A8%3Bs%3A13%3A%22chk_newsgator%22%3Bi%3A9%3Bs%3A14%3A%22chk_blogdigger%22%3Bi%3A10%3Bs%3A12%3A%22chk_moreover%22%3Bi%3A11%3Bs%3A14%3A%22chk_weblogalot%22%3Bi%3A12%3Bs%3A13%3A%22chk_icerocket%22%3B%7D

HTTP/1.x 200 OK
X-Powered-By: PHP/4.4.7
Set-Cookie: blogurl=http%3A%2F%2Foooff.com%2Fphp-affiliate-seo-blog%2F; expires=Mon, 07 Jul 2008 14:41:14 GMT; path=/; domain=.pingomatic.com
Set-Cookie: title=Oooff.com; expires=Mon, 07 Jul 2008 14:41:14 GMT; path=/; domain=.pingomatic.com
Set-Cookie: pinged=a%3A13%3A%7Bi%3A0%3Bs%3A14%3A%22chk_weblogscom%22%3Bi%3A1%3Bs%3A9%3A%22chk_blogs%22%3Bi%3A2%3Bs%3A14%3A%22chk_technorati%22%3Bi%3A3%3Bs%3A11%3A%22chk_myyahoo%22%3Bi%3A4%3Bs%3A13%3A%22chk_pubsubcom%22%3Bi%3A5%3Bs%3A14%3A%22chk_blogstreet%22%3Bi%3A6%3Bs%3A14%3A%22chk_feedburner%22%3Bi%3A7%3Bs%3A11%3A%22chk_syndic8%22%3Bi%3A8%3Bs%3A13%3A%22chk_newsgator%22%3Bi%3A9%3Bs%3A14%3A%22chk_blogdigger%22%3Bi%3A10%3Bs%3A12%3A%22chk_moreover%22%3Bi%3A11%3Bs%3A14%3A%22chk_weblogalot%22%3Bi%3A12%3Bs%3A13%3A%22chk_icerocket%22%3B%7D; expires=Mon, 07 Jul 2008 14:41:14 GMT; path=/; domain=.pingomatic.com
Content-Type: text/html
Content-Length: 2484
Date: Thu, 13 Mar 2008 20:54:40 GMT
Server: LiteSpeed
Connection: close
I’m not going to get into detail on what all that means because in this case we only care about one thing and that’s the very top line. They are using a GET string vs. a post as you can see all the data is be appended to the url. If you don’t know there are two ways to pass data in HTML that’s a GET or POST. GET is going to put all the data in the url. For example look at googles string when you do a search, that’s using GET style data passing. A POST pass is a little more complicated so we’ll save that for the next tutorial. There would be an additional line in the headers that would say post:. With a post we need to add a few more lines to the curl call but we’re not going to do that in this tutorial. Now that we have our url with the data in it lets talk about hwo we’re going to make that into a script to post to the ping.

What I decided to do to make it easier to read is break the string up as you can see we’re using the .= which just keeps appending the string. So you could do this in a single string inline but this is much easier to read. From here I’m going to go to commenting the code for each line.

<?php

// Here is where we're breaking up the url as mentioned above, you can easily see which engines we're pinging now as opposed to trying to find them in the long url
// this is the base url so we're starting our url with that
$url = "http://pingomatic.com/ping/?";
// you'll notice we're using a urlencode function here that makes the text you print url friendly and replaces the chars like spaces with their appropriate url friendly value.
$url .= "title=".urlencode("PHP Posting and Screen Scraping Tutorials");
$url .= "&blogurl=".urlencode("http://oooff.com/php-affiliate-seo-blog/");
$url .= "&rssurl=".("http://oooff.com/php-affiliate-seo-blog/feed");
//as far as I'm concerned leave all the ping places on, the more the better
$url .= "&chk_weblogscom=on";
$url .= "&chk_blogs=on";
$url .= "&chk_technorati=on";
$url .= "&chk_feedburner=on";
$url .= "&chk_syndic8=on";
$url .= "&chk_newsgator=on";
$url .= "&chk_myyahoo=on";
$url .= "&chk_pubsubcom=on";
$url .= "&chk_blogdigger=on";
$url .= "&chk_blogstreet=on";
$url .= "&chk_moreover=on";
$url .= "&chk_weblogalot=on";
$url .= "&chk_icerocket=on";
$url .= "&chk_newsisfree=on";
$url .= "&chk_topicexchange=on";

// now that we have our url composed our url we’re going to call it using curl
// initializes the curl object and sets the url we’re going to get
$ch = curl_init($url);
// tells curl it to follow any redirects
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
// returns the page fetched to a variable in this case $page
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// executes the curl object as we have things set
$page = curl_exec($ch);
// cleans up the curl object nicely
curl_close($ch);
//prints the page got to the screen to make sure it worked right.
echo $page;

?>

A challenge for you, take this script and make it load the data from a csv file which is in the format

title,url,feed
title,url,feed
Here’s a hint there’s another tutorial on this site you can copy that from.

Hope this helps some of you building a simple ping system for your sites and blogs. I might show you a tutorial on how to ping each individually but we’ll see how I feel. Now we wouldn’t want to over ping and abuse this now would we ;)

Enjoy!
Smaxor

Directtrack PHP Class to pull your stats Automatically – Copeac, CPA Empire

Tuesday, February 12th, 2008

I’ve been having a few people ask me for my class to login and pull stats automatically from the different affiliate networks that run on Directtrack’s Affiliate Solution. In one of my previous posts there’s a section of the db called conversions. Well what that section is for is to put all your conversions in from Directtrack. If you go into your directtrack account and hit advanced stats you’re going to see all your subid’s you’ve passed for conversions. This class does that automatically. You’ll need to write a little script to implement the class. But it’ll save you a bunch of time on trying to figure out how to login, grab and parse your affiliate stats. To use this you’ll also need to setup a writable dir for you cookie files. Because when this script log’s in it needs to save a cookie so that it can tell copeac or cpa empire that you’re a verified user.

<?
class DirectTrack {

private $loggedin;
private $login;
private $password;
private $site;
private $cookiefile;
private $start_day;
private $start_month;
private $start_year;
private $end_day;
private $end_month;
private $end_year;

/**
* logs you into the dt system of your choice
*
* @param string $login – login for directtrack
* @param string $password – password for directtrack
* @param string $site – i.e. affiliates.copeac.com or monetizeit.net
* @param string $cookie – cookie location
*/
public function __construct($login,$password,$site,$cookie){

$this->loggedin = false;
$this->login = null;
$this->password  = null;
$this->site = null;
$$this->cookiefile = null;
$this->start_day = null;
$this->start_month = null;
$this->start_year = null;
$this->end_day = null;
$this->end_month = null;
$this->end_year = null;

$this->setLogin($login);
$this->setPassword($password);
$this->setSite($site);
$this->setCookieLocation($cookie);
$this->DTLogin();

}
/**
* deletes the cookie file on destroying the object remember to unset your object
*
*/
public function __destruct(){
unlink($this->cookiefile);
}

/**
* login setter, url encodes
*
* @param string $login
*/
public function setLogin($login){ $this->login = urlencode($login); }
/**
* password setter, url encodes
*
* @param string $password
*/
public function setPassword($password){ $this->password = urlencode($password);}
/**
* Directtrack site domain setter
*
* @param string $site – i.e. affiliates.copeac.com or monetizeit.net
*/
public function setSite($site){ $this->site = $site;}
/**
* setter for the cookie directory, randomizes the cookie as well incase multi threads are running
* Please make sure your directory is writable
*
* @param string $cookie
*/
public function setCookieLocation($cookie){
$this->cookiefile = $cookie.”/cookie”.rand(11111111,99999999).”.txt”;
}
/**
* getter for the currently generated cookie file location
*
* @return string
*/
public function getCookieLocation(){return $this->cookiefile;}
/**
* Checks the status of being logged In
*
* @return array – array(‘msg’=> ”,’status’=>”) 0 logged out, 1 logged in.
*/
public function LoggedInStatus(){
if($this->loggedin){
return array(“msg”=>”Logged In!”,”status”=>1);
}else{
return array(“msg”=>”Not logged in!”,”status”=>0);
}
}
/**
* sets the start date for the report you’re looking for
*
* @param int $day
* @param int $month
* @param int $year
*/
public function setStartDate($day,$month,$year){
$this->start_day = $day;
$this->start_month = $month;
$this->start_year = $year;

}
/**
* sets the ending date for the report you’re looking for
*
* @param int $day
* @param int $month
* @param int $year
*/
public function setEndDate($day,$month,$year){
$this->end_day = $day;
$this->end_month = $month;
$this->end_year = $year;

}
/**
* Combo function which gets the advanced report from direct track that has all the
* specific sub-id data then parses it into a multi dimensional array
*
* @return array – array[line][fields]
*/
public function AdvancedStats(){

if(!$this->loggedin){
$this->DTLogin();
}

$stat_page = $this->DTfetchAdvancedStats();
return $this->csv2array($stat_page);

}
/**
* extends AdvnacedStats, and then inserts the data into the db
*
* @return array – advanced stats array incase you want it for something else
*/
public function AdvancedStats2DB(){
$stats = $this->AdvancedStats();
$this->DBconversionInsert($stats);
return $stats;

}
/**
* gets totals based on account for dates set
*
*/
public function Totals(){
$csv = $this->DTfetchTotals();
return $this->csv2array($csv);
}
/**
* NOT COMPLETE
* -Needs the regex to work properly
* -paging for sites that have multiple pages of results
*
* @return array
*/
public function AllOffers(){
$campaign_page = $this->DTfetchAllCamapigns();

$regex_sections = “/<\/a><\/td>.+?program_id=(\d*)&.+?\’>(.+?)<.+?top\’>\$*(.+?)/*<*.+?’>(.+?)<.+?’>(.+?)</s”;
preg_match_all($regex_sections,$campaign_page,$matches);

foreach($matches[0] as $section){
echo “<br><br>$section<br><br>”;
//get section name
$regex_section = “/Category: (.+?)</”;
preg_match($regex_section,$section,$match);
$section_name = “<b>”.$match[1].”</b>”;

$regex_offers = “/program_id=(\d*)&/s”;
preg_match_all($regex_offers,$section,$matches);
var_dump($matches);
exit;

$offers = array();
$sets = 0;
foreach ($matches as $data){

if($sets != 0){
$i = 0;
foreach ($data as $offer_data){

$offers[$i][] = $offer_data;
$i++;
}
}
$sets++;
exit;
}
array_unshift($offers,$section_name);
var_dump($offers);
}
return $offers;
exit;

}
//// Private //////

/**
* the function that logs into your directtrack account
*
* @return string – curl output
*/
private function DTLogin(){

$url = “https://$this->site/index.html”;
$post = “DL_AUTH_USERNAME=$this->login&DL_AUTH_PASSWORD=$this->password”;

$ch = new CurlPost($url,$post);
$ch->setCookie($this->cookiefile);
$ch->SSL();
$c_out = $ch->execute();
unset($ch);
if(1){ //parse for successful login
$this->loggedin = true;
}
return $c_out;
}
/**
* gets the advanced stats once logged in
*
* @return string – curl output – csv format
*/
private function DTfetchAdvancedStats(){

$url = “https://$this->site/partners/monthly_affiliate_stats.html?program_id=0&affiliate_stats_start_month=$this->start_month&affiliate_stats_start_day=$this->start_day&affiliate_stats_start_year=$this->start_year&affiliate_stats_end_month=$this->end_month&affiliate_stats_end_day=$this->end_day&affiliate_stats_end_year=$this->end_year&breakdown=cumulative&get_lead_info=Download+Optional+Info”;

$ch = new CurlGet($url);
$ch->useCookie($this->cookiefile);
$ch->SSL();
$curl_stats = $ch->execute();
unset($ch);
return $curl_stats;
}
/**
* breaks csv data into a multi-dim array with array[line][fields]
*
* @param string $curl_data – csv from advanced page
* @return array – multi-dim array[line][fields]
*/
private function csv2array($curl_data){

$return = array();
//lines to array
$stats = explode(“\n”,trim($curl_data));

foreach($stats as $line){
//fields to array
$fields = explode(“,”,trim($line));
$record = array();
foreach($fields as $field){
$record[] = trim($field);
}
$return[] = $record;
}
return $return;
}
/**
* takes the multi-dim array from DTparseAdvancedStats and inserts it into a db
*
* @param array $stats
*/
private function DBconversionInsert($stats){

$count = 0;
foreach($stats as $row){
if($count != 0){

//assignments
$click_id        = trim($row[2]);
$source         = $this->site;
$date             = $this->_ChangeDateFormat($row[0]);
$campaign        = addslashes(trim($row[1]));
$campaignID     = trim($row[3]);
$transactionID    = trim($row[4]);
$lineitemID        = trim($row[5]);
$commission     = $this->_CleanCommission($row[6]);

$sql = “INSERT INTO `conversions` (`click_id`,`source`,`date`,`campaign`,`campiagnID`,`transactionID`,`lineitemID`,`commission`) VALUES (‘$click_id’,'$source’,'$date’,'$campaign’,'$campaignID’,'$transactionID’,'$lineitemID’,'$commission’)”;

//echo “$sql<br>”;
if(!strpos($click_id,”blogs”))
{
mysql_query($sql);
}
//if(mysql_error()){ echo mysql_error().”\n”; }

}
$count ++;
}
}
/**
* gets the totals for all sales by campaign
*
* @return string – curl output
*/
private function DTfetchTotals(){

$url = “https://$this->site/partners/monthly_affiliate_stats.html?program_id=0&affiliate_stats_start_month=$this->start_month&affiliate_stats_start_day=$this->start_day&affiliate_stats_start_year=$this->start_year&affiliate_stats_end_month=$this->end_month&affiliate_stats_end_day=$this->end_day&affiliate_stats_end_year=$this->end_year&breakdown=cumulative&get_csv=1″;

$ch = new CurlGet($url);
$ch->useCookie($this->cookiefile);
$ch->SSL();
$curl_stats = $ch->execute();
unset($ch);
return $curl_stats;
}
/**
* once logged in curl to get the campaigns
*
* @return string – curl page
*/
private function DTfetchAllCamapigns(){
$url = “https://$this->site/partners/search_program_categories.html”;

$ch = new CurlGet($url);
$ch->useCookie($this->cookiefile);
$ch->SSL();
$curl_stats = $ch->execute();
unset($ch);
return $curl_stats;
}

// private functions
private function _ChangeDateFormat($date)
{
$parts = explode(“/”,$date);
$date = $parts[2].”-”.$parts[1].”-”.$parts[0];
//echo $date.”<br>”;
return $date;
}
private function _CleanCommission($dollar)
{
return str_ireplace(“$”,”",$dollar);
}
}

// THIS IS HOW YOU USE THE CLASS

//$cookieDir = “cookies”;
//$dt = new DirectTrack(‘my@email.com’,'password’,'copec.com’,$cookieDir);
//$dt->setStartDate(1,6,2007);
//$dt->setEndDate(18,6,2007);
//var_dump($dt->LoggedInStatus());
//echo $dt->getCookieLocation();
//var_dump($dt->AdvancedStats());
//var_dump($dt->Stats2DB());
//var_dump($dt->Totals());
//var_dump($dt->AllOffers());
//unset($dt);

?>

P.S. Sorry for the crappy display of the code. Unlike Uberaffiliate I don’t make money from my blog so it doesn’t get that much attention. :D

How to find Good Keywords From your Own Tracking – using the OOOFF Tracking system

Monday, December 17th, 2007

As you probably know one of the best places to find keywords for you campaigns is in you own logs or tracking. And the most up to date info is tracking the people come to your site via search queries. Now you can track these in your your logs or a click tracking system like the one I’ve been laying out on here. One strategy I like to use, on Adwords for doing keyword research is to bid on single word terms. However to do this you don’t want to use your main account. I’d suggest setting up a new junk account and dumping in all the single words you can like “car” or “house” using phrase match and exact match. Then bid a decent amount so you make it up to the first page. These keywords aren’t that hard to get for fairly cheap as it’s hard to maintain a good CTR and not get QS’d out. Then run it as long as they let you until you get Quality Score screwed. Then go through your logs and pull all the queries out and look for themes and ideas of stuff that might bring traffic. Real search data is gold compared to those crappy keyword tools like spyfu or keywordspy.

For those of you using my click tracking script I’m going to share the code for scraping out the queries from google. With this you can pull the keywords that converted or any keywords from any click that came to your site. If you want conversions just add a http://www.domain.com/queryscript.php?type=conv


<?

dbconnect();

$sql = "SELECT DISTINCT(clicks.referer) FROM clicks, conversions WHERE ";
if($_GET['type'] == 'conv'){
$sql .= "clicks.id = conversions.click_id AND ";
}
$sql .= "
clicks.source = 'ggl'
AND clicks.country = 'uk'
AND clicks.referer LIKE '%christmas%'
AND clicks.matchtype = 'e'
ORDER BY clicks.id DESC";

$q = mysql_query($sql) or die(mysql_error());
$myarray = array();
while ($ref = mysql_fetch_assoc($q))
{
$ref = explode("?",$ref['referer']);
parse_str($ref[1],$output);
if(isset($output['q']))
{
$qstr = strtolower($output['q']);
}elseif (isset($output['p'])){
$qstr = $output['p'];
}

  if(isset($qstr))
{
$ex = array_key_exists($qstr,$myarray);
if($ex)
{
$myarray[$qstr] = $myarray[$qstr] + 1;
}else{
$myarray[$qstr] = 1;
}
}
unset($qstr);
}

sort($myarray);
foreach($myarray as $keyw=>$value){
//echo "$keyw"; this is if you just want the query for cutting and pasting
echo "$keyw,$value"; // this is if you want the keyword with the count of the number of queries it showed in.
}
?>

This is pretty crude and ripped right from my own system. But it’ll pull the keywords from the queries in the referers from Google.

Take these queries and dump them into their own campaign with exact match and phrase match only. No Broad match. And then watch what happens and make you’re adjustments from there. In another month do it again. You’ll come up with all kinds of good words you never would have thought of on your own.

Update to PPC Click Tracking Script for Yahoo and MSN…

Friday, December 14th, 2007

Sorry for the long time between posts. Just things have been very busy lately. Here’s an update to the click tracking code for tracking your conversions to include yahoo and msn pay per click. I just pulled this direct out of my system. This also includes a way to exclude bots by IP. Using the list from iplists.com I in a file called ip_list.txt in the same directory as you tracking file. So that your tracking doesn’t record bot visits. Below have included the updated sql schema for click tracking, it’s a little messy and could be better but just haven’t had time to improve it. If someone has a better click tracking schema around I’d be interested in seeing it.

So our urls to use to track

Yahoo Search Marketing:

http://www.yourdomain.com/index.php?s=ysm&n=1

To make this work properly you need to enable tracking URL’s in your account. This will pass all the appropriate variable automatically.

Google Adwords:

http://www.yourdomain.com/index.php?s=ggl&qs={keyword}&k={keyword}&n=1

This could be improved to scrape the query out of the referer and use that for the Query String in the table, it’s on the list.

MSN Adcenter:

http://www.yourdomain.com/index.php?k={Keyword}&s=msn&qs={QueryString}&mt={MatchType}&oii={OrderItemId}&ai={AdId}&n=1


<?
$keyword = addslashes(trim($_GET['k']));
session_start();
DEFINE('DB_HOST','host');
DEFINE('DB_USER','username');
DEFINE('DB_PASS','password');
DEFINE('DB_PRIMARY','tracking');
@mysql_connect(DB_HOST,DB_USER,DB_PASS);
@mysql_select_db(DB_PRIMARY);
if(mysql_ping() == true)
{
if(!isset($_SESSION['id']))
{
// Server variables
$ip = $_SERVER['REMOTE_ADDR'];
$referer = $_SERVER['HTTP_REFERER'];
$useragent = $_SERVER['HTTP_USER_AGENT'];
$source = addslashes(trim($_GET['s']));
$site = addslashes(trim($site));
$niche = trim($_GET['n']);
if($niche == ''){ $niche = 1; }
$loc = trim($_GET['loc']);
if($loc == ""){ $loc = "us"; }
if($source != "ysm")
{
$keyword = str_ireplace("_"," ",$keyword);
$query = addslashes(trim($_GET['qs']));
$matchtype = addslashes(trim($_GET['mt']));
$item_id = addslashes(trim($_GET['oii']));
$ad_id = addslashes(trim($_GET['ai']));
$clickid = addslashes(trim($_GET['gclid']));
}else{
$query = addslashes(trim($_GET['OVRAW']));
$keyword = addslashes(trim($_GET['OVKEY']));
$matchtype = addslashes(trim($_GET['OVMTC']));
$ad_id = addslashes(trim($_GET['OVADID']));
}
if(!CheckBotIp($ip))
{
$sql = "INSERT INTO `clicks` (`keyword`,`source`,`ip`,`referer`,`useragent`,`time`,`site`,`querystring`,`matchtype`,`orderitemid`,`adid`,`clickid`,`niche`,`country`) VALUES ('$keyword','$source','$ip','$referer','$useragent',NOW(),'$site','$query','$matchtype','$item_id','$ad_id','$clickid','$niche','$loc')";
//echo $sql;
mysql_query($sql);// or die(mysql_error());
$id = mysql_insert_id();
$_SESSION['id'] = $id;
$_SESSION['keyword'] = $keyword;
$_SESSION['referer'] = $referer;
}
}else{
$id = $_SESSION['id'];
$keyword = $_SESSION['keyword'];
$referer = $_SESSION['referer'];
}
}
/**
* Functions
*/
function CheckBotIp($ip)
{
$flag = 1;
$ips = file("/home/ip_list.txt");
$ips = array_map("trim",$ips);
foreach ($ips as $listip)
{
if($ip == $listip)
{
return 1;
}
}
}
?>

Here’s the updated schema to record for all systems. As I mentioned before it’s crude and needs some work so if anyone wants to contribute I’d be happy to post it and give you credit.

– phpMyAdmin SQL Dump
– version 2.11.0-dev
– http://www.phpmyadmin.net

– Host: localhost
– Generation Time: Dec 14, 2007 at 02:34 PM
– Server version: 5.0.22
– PHP Version: 5.1.6

SET SQL_MODE=”NO_AUTO_VALUE_ON_ZERO”;


– Database: `tracking`

– ——————————————————–


– Table structure for table `clicks`

CREATE TABLE IF NOT EXISTS `clicks` (
`id` double NOT NULL auto_increment,
`keyword` varchar(255) NOT NULL default ”,
`source` varchar(255) NOT NULL default ”,
`ip` varchar(15) NOT NULL default ”,
`useragent` varchar(255) NOT NULL default ”,
`referer` varchar(255) NOT NULL default ”,
`time` datetime NOT NULL default ‘0000-00-00 00:00:00′,
`site` varchar(100) NOT NULL default ”,
`querystring` varchar(255) NOT NULL default ”,
`matchtype` char(2) NOT NULL default ”,
`orderitemid` varchar(255) NOT NULL default ”,
`adid` varchar(255) NOT NULL default ”,
`medium` varchar(50) NOT NULL,
`network` varchar(10) NOT NULL,
`clickid` varchar(50) NOT NULL,
`niche` int(11) NOT NULL,
`country` varchar(20) NOT NULL,
PRIMARY KEY (`id`),
KEY `medium` (`medium`),
KEY `source` (`source`),
KEY `time` (`time`),
KEY `useragent` (`useragent`),
KEY `country` (`country`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=0;

– ——————————————————–


– Table structure for table `conversions`

CREATE TABLE IF NOT EXISTS `conversions` (
`id` double NOT NULL auto_increment,
`click_id` double NOT NULL,
`source` varchar(50) NOT NULL,
`date` date NOT NULL,
`campaign` varchar(255) NOT NULL,
`campiagnID` varchar(20) NOT NULL,
`transactionID` varchar(50) NOT NULL,
`lineitemID` varchar(20) NOT NULL,
`commission` decimal(10,2) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `transactionID` (`transactionID`),
KEY `click_id` (`click_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=0;

Easy “PHP Proxy Checker” Writing Tutorial

Wednesday, October 31st, 2007

I started to write this on Eli’s forum but decided to add it here so everyone could reference it.

If you have a list of proxies that you’ve got from somewhere and want to verify if they’re good or not this is simple script that will read a text file and check them.

First we’ll make a text file with our proxies on each line of the file in the format IP:PORT with one per line.

127.127.127.127:2487
123.123.123.123:3248

then save that text file as “proxylist.txt” in the same directory as the php file you’re going to make. Then we’ll start our php file with our proxy checking in it. Here’s the complete script that just echo’s the status of each proxy out to the screen. We’ll make a few changes and have it write a new file with only the good proxies next.

// This is the page that that we're going to request going through the proxy
$testpage = "http://www.google.com";
// This loads all the proxies from the file into an array
$proxies = file("proxylist.txt");
// Here we loop through each cell of the array with the proxies in them testing each one until we get to the end of the array
foreach($proxies as $proxy)
{
// This script utilizes cURL which is library you can read more about
//using curl in my intro tutorials
// starting curl and setting the page to get
$ch = curl_init($testpage);
// sets the proxy to go through
curl_setopt($ch,CURLOPT_PROXY,$proxy);
// sets to use a tunnel proxy which most http proxies are
curl_setopt($ch,CURLOPT_HTTPTUNNELPROXY,$proxy);
// makes the curl call do it's work based on what we've set previously and
//returns that fetched page to $page
$page = curl_exec($ch);
// cleans up the curl set
curl_close($ch);
// this will check that there was some html returned, now some sites might block some
//proxies so you'd want to set for that specific site in the $testpage var and then
//find something on that page to look for with the below function.
$check = stripos($page,'</html>');
// if there was a match in the stripos (string postion) function echo that the
//proxy got the data and works
if($check > 0)
{
echo $proxy." Works!
";
// or else echo it doesn't work
}else{
echo $proxy." Is Dead!
";
}
}
?>

There’s your code. The gist of this is that we load each line from a file into an array. Then we loop through each array element checking if we can get the google page going through the proxy. Then if it pulls data it prints on the screen that the proxy works or if it doesn’t get something returned it doesn’t.

Now we might not want to print things to the screen and would rather make a new file with the the good proxies. To do that we’d swap this code:

if($check > 0)

{

 echo $proxy." Works!";

// or else echo it doesn't work

}else{

 echo $proxy." Is Dead!";

}

with:

if($check > 0){file_put_content("newproxylist.txt",$proxy."n",FILE_APPEND);}

rename('proxylist.txt','proxylistold.txt)';

rename('newproxylist.txt','proxylist.txt');

}

And that will write a new file and add each of the good proxies to it. Then rename the the original file to proxylistold.txt in case there was an error it’s good to have a backup. Then we rename the newpoxylist.txt to the standard proxylist.txt and it’s all fresh and ready to go. There you have it a nice simple proxy checker.

P.S. make sure you make the dir that they’re in writable as there’ll be issues with creating a new file in an unwritable dir.

P.P.S Trying this new code plug-in and well let me tell yah. IT’S A HUGE PAIN IN THE ASS!