Display Google Keywords that brought a user to the site - php

I am looking to display something like:
Hello, you've reached this site by looking for [google keyword(s)]
I'm pretty sure I've seen this done before but I am having troubles figuring out how to grab the keywords that were used to lead a user to my site. Anyone know the answer?

You need to get the referring URL and then strip out everything for the "q" query string. This will give you the query that was used to get you to your page.

Using the referrer (http://www.netmechanic.com/news/vol4/javascript_no14.htm) you can find where the user comes from. Then it's just a matter of parsing it correctly.
I saw this script :
function getkeywords() {
var x = document.referrer;
var lastparturl = 0;
if (x.search(/google/) != -1) {
lastparturl = x.indexOf("&btnG=Google+Search");
x = x.slice(38,lastparturl);
x = x.concat("via google");
}
else if (x.search(/yahoo/) != -1) {
lastparturl = x.indexOf("&ei=UTF-8&iscqry=&fr=sfp");
x = x.slice(63,lastparturl);
x = x.concat("via yahoo");
}
else if (x.search(/ask.com/) != -1) {
lastparturl = x.indexOf("&search=search&qsrc=0&o=0&l=dir");
x = x.slice(25,lastparturl);
x = x.concat("via ask");
}
else if (x.search(/dogpile/) != -1) {
lastparturl = x.indexOf("/1/417/TopNavigation/Relevance/iq=true/zoom=off/_iceUrlFlag=7?_IceUrl=true");
x = x.slice(46,lastparturl);
x = x.concat("via dogpile");
}
else if (x.search(/altavista/) != -1) {
lastparturl = x.indexOf("&kgs=1&kls=0");
x = x.slice(48,lastparturl);
x = x.concat("via altavista");
}
else {
x = "no keywords available";
}
x = x.replace(/+/, " ");
return x;
}
Here http://www.webmonkey.com/codelibrary/Get_Referrer_Keywords
I'm not sure if it works perfectly, but it worked OK when I reached their website through google.
I also saw that some scripts that you can download do that, for instance: http://webscripts.softpedia.com/script/Search-Engines/Keyword-Grabber-45299.html
Again, this will need to be tested.

Related

How to prevent undefined variable error from showing? (I know the variable is null in this case)

For part of a project i am working on in school i am building a room booking system. As part of this system, i have a page where users can enter criteria for a room and the page will return available rooms that fit that criteria and are free for booking. If a users search does not return any results i intend to lower the criteria entered, display a room that fits the altered criteria and display a message to the user informing them of the altered criteria. The call to function suggestroom() is shown here.
} else {
$reducecapacity = 1;
do {
$booking = new Booking();
$suggestedrooms = $booking->suggestroom(($capacity - $reducecapacity), $appletv, $printer);
$reducecapacity = $reducecapacity + 1;
} while($suggestedrooms === null);
echo 'This room has a cacpacity of: ' . ($capacity-($reducecapacity-1));
for($x=0; $x<count($suggestedrooms); $x++) {
echo $suggestedrooms[$x];
}
}
Public function SuggestRoom($capacity, $appletv, $printer) {
if($appletv == 1 and $printer ==0) {
$roomname = DB::GetInstance()->query("SELECT roomname FROM room WHERE capacity >= '$capacity' AND appletv ='$appletv'");
} elseif($appletv == 0 and $printer == 1) {
$roomname = DB::GetInstance()->query("SELECT roomname FROM room WHERE capacity >= '$capacity' AND printer = '$printer'");
} elseif($appletv == 1 and $printer == 1) {
$roomname = DB::GetInstance()->query("SELECT roomname FROM room WHERE capacity >= '$capacity' AND appletv ='$appletv' AND printer = '$printer'");
} else {
$roomname = DB::GetInstance()->query("SELECT roomname FROM room WHERE capacity >= '$capacity'");
}
$roomcount = $roomname->count();
if($roomcount == 0) {
echo 'No classes match your criteria';
} else {
for($x=0; $x<$roomcount; $x++) {
$RoomArray[$x] = $roomname->results()[$x]->roomname;
}
}
$LoopCount = 0;
$EndLoop = false;
$RNDnum = 0;
$availableroomcount = 0;
do {
$suggestedRoom = $RoomArray[$RNDnum];
$getRoomID = DB::GetInstance()->query("SELECT roomid FROM room WHERE roomname = '$suggestedRoom'");
$roomid = $getRoomID->results()[0]->roomid;
$bookingid = Input::get('bookingdate') . Input::get('period') . $roomid;
$CheckIfBooked = DB::GetInstance()->query("SELECT bookingid FROM booking WHERE bookingid = '$bookingid'");
if($CheckIfBooked->count() ==0) {
$availablerooms[$availableroomcount] = $suggestedRoom;
$availableroomcount = $availableroomcount+1;
}
if($LoopCount===$roomcount-1) {
$NoRoomMessage = true;
$EndLoop = true;
$suggestedRoom = null;
}
$LoopCount = $LoopCount+1;
$RNDnum = $RNDnum +1;
} while ($EndLoop <> 1);
return $availablerooms;
}
Thus, when there are no bookings, a null array will be returned to suggested rooms and this will continue until a room is found (if not, i will make it so other criteria is changed, not that far ahead yet).
A room can be found, and the code works however for x amount of times that the code is ran before a room is found i.e an empty array is returned, i get an undefined variable message. How can i get around this?
Switching off notices, warnings, errors is not the best way to code.
And unlike the above answers I prefer to always initialize a variable rather then using isset().
Use isset/empty
if(isset($var1) || !empty($var1)){
//do something
} else {
//do another
}

Why is Apache inserting comment into some of my HTML output?

While running my code through W3C's HTML validator for HTML5, I noticed that some of my files had this comment inserted before the tag:
<!-- This file should NOT be stored in the web root directory (or any sub-directory thereof) If this is not possible, place it in the 'include' directory and restrict access via Apache's .htaccess files -->
This only seems to happen with pages that are accessed via POST requests, though I have been unable to pin down any cause, nor have searches turned up anything.
I am using mod rewrites and the HTML is generated from multiple files from webroot/views/ and webroot/includes/, but other pages that are similarly generated do not have this issue.
Anyway, I normally wouldn't worry about it, but when sending an xml request to dynamically update a price field, the xml return results, which were supposed to be just the price value as a number, were prefixed by that entire comment.
Now, I can remove it in my application code, which is what I have done, but I'd really like to know under what circumstances Apache decides to inject this comment into outputted HTML files.
For reference, here is my JS to send/handle the xml request:
<script type="text/javascript">
/**
* Updates the currently displayed price based on currently selected options
* #param category_id Id of currently selected category
*/
function updatePrice(category_id) {
if (category_id === undefined || category_id < 1) {
return false;
}
if (!document.getElementsByTagName) { return; }
var aSelect = document.getElementsByTagName("SELECT");
var data = [];
data.push("category_id=" + category_id);
for (var i = 0; i < aSelect.length; i++) {
var sid = aSelect[i].id;
if (sid !== undefined && sid.indexOf("select_") > -1) {
data.push(sid + '=' + aSelect[i].value);
}
}
data = data.join('&');
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
// Hack to remove Apache's auto-generated comment/warning at top of some pages
var text = xmlhttp.responseText;
text = (text.length > 0 ? text.substring(text.lastIndexOf('>') + 1).trim() : '');
var price = document.getElementById("product-price");
if (price != null) {
price.value = (text.length < 1 ? 'N/A' : ('$' + text));
}
}
}
xmlhttp.open("POST", "rental_update_price.php", true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send(data);
}
</script>
And here is the php file that processes the request:
<?php
if (!isset($errors)) { $errors = array(); }
if (!isset($notifications)) { $notifications = array(); }
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (empty($_POST['category_id']) || !is_numeric($_POST['category_id'])) {
die('Sorry, there has been a system error.');
}
$category_id = (int) $_POST['category_id'];
require './includes/config.inc.php';
require MYSQL;
$att_tbl = selectWithCondition($dbc, 'att_table', 'rental_categories', 'id', $category_id, 'i', 'LIMIT 1');
if ($att_tbl === FALSE) {
die('Failed to retrieve product attribute table from database.');
}
// Retrieve all 'select' keys and values to query exact product id and price
$selected = array();
foreach($_POST AS $k=>$v) {
if (strpos($k, 'select_') > -1) {
// All select fields should be foreign key references, i.e. positive integers
if (ctype_digit($v) && $v > 0) {
$selected[(str_replace('select_', '', $k) . '_id')] = (int) $v;
} else {
$errors[$k] = 'Invalid value';
}
}
}
if (empty($selected)) {
die('No columns selected.');
}
// TODO select price instead of id
$q = "SELECT p.id FROM products p";
$where = '';
foreach($selected AS $k=>$v) {
if (empty($where)) {
$where = "t.$k=$v";
} else {
$where .= " AND t.$k=$v";
}
}
$q .= " JOIN $att_tbl t ON t.product_id=p.id WHERE $where LIMIT 1";
if (($r = $dbc->query($q))) {
if ($row = $r->fetch_assoc()) {
// Generate dummy price value for testing:
echo number_format((((int) $row['id']) * 31) / 100, 2);
}
$r->close();
} else {
$notifications['error'] = 'A system error has occurred. The system administrator will be notified automatically.';
$notifications['error_log'] = 'Error No: ' . $dbc->errno . '-' . $dbc->error;
}
}
require MYSQL;
if MYSQL is a file, give it an extension .php so it doesn't bypass the PHP interpreter.
I think PHP does print the warning when you include a file which is not parsed.
Answering my own question since it was one of those where you look for days and when you finally break down and ask, it becomes glaringly obvious almost immediately.
In my MYSQL file, I had that comment at the top, even before the php tags, and in certain situations the MYSQL file is included before any other HTML output, which then results in that comment being displayed.
Moving the comment to within the php tags so that it is not considered HTML fixes the issue.
Thanks to all who commented.

PHP recently viewed script to session array

I've been given this bit of code:
if(isset($_GET['viewevent'])) {
if(count($_SESSION['e_lastviewed']) == 0) {
$_SESSION['e_lastviewed'][0] = $_GET['viewevent'];
} else if(!in_array($_GET['viewevent'], $_SESSION['e_lastviewed'])) {
$_SESSION['e_lastviewed'][2] = $_SESSION['e_lastviewed'][1];
$_SESSION['e_lastviewed'][1] = $_SESSION['e_lastviewed'][0];
$_SESSION['e_lastviewed'][0] = $_GET['viewevent'];
}
}
if($_GET['show']) {
$_SESSION['show'] = $_GET['show'];
} else if($_SESSION['show']=='') {
$_SESSION['show'] = "all";
}
It apparently saves ID's of recently viewed items, so i need to put these id's into an array.
Would this work?
$my_array = array($_SESSION['e_lastviewed'][2],$_SESSION['e_lastviewed'][1],$_SESSION['e_lastviewed'][0]);
I've ran it but it displays blank results (not sure if thats due to me not doing it right or incomplete code...Have i missed something? I'm not sure if i completley understand the script i was given...
try this:
if ( !isset($_SESSION['e_lastviewed']) )
$_SESSION['e_lastviewed'] = array();
// alt: while(count($_SESSION['e_lastviewed']) > 2 ) {
if(count($_SESSION['e_lastviewed']) > 2 ) {
array_shift($_SESSION['e_lastviewed']); // drop off from 3
array_unshift($_SESSION['e_lastviewed'],$_GET['viewevent']); // insert in the beginning
if($_GET['show']) {
$_SESSION['show'] = $_GET['show'];
} else if($_SESSION['show']=='') {
$_SESSION['show'] = "all";
}

Processing animation extremely choppy when getting data from a remote host

I am connecting to a remote web server to get mouse movements stored in a database. The processing program I've written to animate these movements has been INCREDIBLY choppy since putting the code on the server. I realize this is because rather than running locally it's got to fetch the information, but is it possible to speed things up a bit? Here's the code I'm using
String get_users = "http://example.com/get_users.php";
String get_data = "http://example.com/get_data.php?user=";
ArrayList arrows;
PImage mouse;
int[] user_ids;
int num_users;
void setup() {
size(1024, 768);
frameRate(24);
smooth();
noStroke();
mouse = loadImage("arrow-clear.png");
arrows = new ArrayList();
getUsers();
for (int i = 0; i < num_users; i++){
arrows.add(new Arrow(user_ids[i], i*400, 2*i*100));
}
}
void getUsers(){
user_ids = int(loadStrings(get_users));
num_users = user_ids.length;
println(num_users);
}
void draw() {
background(0);
if (frameCount % 600 == 0){
getUsers();
for (int i = 0; i < num_users; i++){
arrows.add(new Arrow(user_ids[i], i*400, 2*i*100));
}
}
for (int i = arrows.size()-1; i >= 0; i--) {
Arrow arrow = (Arrow) arrows.get(i);
arrow.move();
if (arrow.finished()) {
arrows.remove(i);
}
}
}
class Arrow {
String[] all_moves, move_pairs, new_moves;
int[] moves;
float x;
float y;
int id;
int i = 0;
Boolean is_done = false;
Arrow(int tempID, float tempX, float tempY) {
all_moves = loadStrings(get_data + tempID);
id = tempID;
x = tempX;
y = tempY;
if (all_moves.length > 0){
move_pairs = shorten(split(all_moves[0], "|"));
}
}
void move() {
if (move_pairs != null){
if (i < move_pairs.length){
moves = int(split(move_pairs[i], ","));
image(mouse, moves[0], moves[1]);
++i;
} else {
all_moves = loadStrings(get_data + id);
if (all_moves.length > 0){
new_moves = shorten(split(all_moves[0], "|"));
for (int j = 0; j < new_moves.length; j++){
move_pairs = append(move_pairs, new_moves[j]);
}
println(move_pairs);
} else {
is_done = true;
}
}
} else {
is_done = true;
}
}
boolean finished() {
if (is_done) {
return true;
} else {
return false;
}
}
}
EDIT: To clarify: the Processing application doing all the animation is running locally. The X and Y points for the mouse is the only thing getting downloaded from the server.
You want to get all of the movement data (or large chunks of it) down to the client, and let the client do the work of animating everything.
I doubt it is a good idea to download the movement data on every single frame. If you don't need such detailed responsiveness, fetch a batch of movements from the server periodically and queue them for the draw method. Otherwise make sure the server sends only the data needed. I realized that you only use the first line of the data fetched from the server - all_moves[0]. If there is indeed only one line at all - fine.
You should consider using createInput(URL) and read from that stream, this way you wouldn't need to open a new input stream for every movement requested, but your server side code must be able to maintain the streams and write to them continuously.

Is there a piece of public code available to create a page index using PHP?

I have a MySQL table holding lots of records that i want to give the user access to. I don't want to dump the entire table to the page so i need to break it up into 25 records at a time, so i need a page index. You have probably seen these on other pages, they kind of look like this at the base of the page:
< 1 2 3 4 5 6 7 8 9 >
For example, when the user clicks on the '4' link, the page refreshes and the offset is moved on (4th page x 25 records). Here is what i already have:
function CreatePageIndex($ItemsPerPage, $TotalNumberOfItems, $CurrentOffset, $URL, $URLArguments = array())
{
foreach($URLArguments as $Key => $Value)
{
if($FirstIndexDone == false)
{
$URL .= sprintf("?%s=%s", $Key, $Value);
$FirstIndexDone = true;
}
else
{
$URL .= sprintf("&%s=%s", $Key, $Value);
}
}
Print("<div id=\"ResultsNavigation\">");
Print("Page: ");
Print("<span class=\"Links\">");
$NumberOfPages = ceil($TotalNumberOfItems / $ItemsPerPage);
for($x = 0; $x < $NumberOfPages; $x++)
{
if($x == $CurrentOffset / $ItemsPerPage)
{
Print("<span class=\"Selected\">".($x + 1)." </span>");
}
else
{
if(empty($URLArguments))
{
Print("".($x + 1)." ");
}
else
{
Print("".($x + 1)." ");
}
}
}
Print("</span>");
Print(" (".$TotalNumberOfItems." results)");
Print("</div>");
}
Obviously this piece of code does not create a dynamic index, it just dumps the whole index at the bottom of the page for every page available. What i need is a dynamic solution that only shows the previous 5 pages and next 5 pages (if they exist) along with a >> or something to move ahead 5 or so pages.
Anybody seen an elegant and reusable way of implementing this as i feel i'm re-inventing the wheel? Any help is appreciated.
Zend Framework is becoming a useful collection and includes a Zend_Paginator class, which might be worth a look. Bit of a learning curve and might only be worth it if you want to invest the time in using other classes from the framework.
It's not too hard to roll your own though. Get a total count of records with a COUNT(*) query, then obtain a page of results with a LIMIT clause.
For example, if you want 20 items per page, page 1 would have LIMIT 0,20 while page 2 would be LIMIT 20,20, for example
$count=getTotalItemCount();
$pagesize=20;
$totalpages=ceil($count/$pagesize);
$currentpage=isset($_GET['pg'])?intval($_GET['pg']):1;
$currentpage=min(max($currentpage, 1),$totalpages);
$offset=($currentpage-1)*$pagesize;
$limit="LIMIT $offset,$pagesize";
It's called Pagination:
a few examples:
A nice one without SQL
A long tutorial
Another tutorial
And Another
And of course.. google
How about this jQuery-plugin?
So all the work is done on the clientside.
http://plugins.jquery.com/project/pagination
demo: http://d-scribe.de/webtools/jquery-pagination/demo/demo_options.htm
Heres an old class I dug out that I used to use in PHP. Now I handle most of it in Javascript. The object takes an array (that you are using to split the stack into pages) and return the current view. This can become tedious on giant tables so keep that in mind. I generally use it for paging through small data sets of under 1000 items. It can also optionally generate your jump menu for you.
class pagination {
function pageTotal($resultCount, $splitCount) {
if (is_numeric($resultCount) && is_numeric($splitCount)) {
if ($resultCount > $splitCount) {
$pageAverage = (integer)$resultCount / $splitCount;
$pageTotal = ceil($pageAverage);
return $pageTotal;
} else {
return 1;
}
} else {
return false;
}
}
function pageTotalFromStack($resultArray, $splitCount) {
if (is_numeric($splitCount) && is_array($resultStack)) {
if (count($resultStack) > $splitCount) {
$resultCount = count($resultStack);
$pageAverage = (integer)$resultCount / $splitCount;
$pageTotal = ceil($pageAverage);
return $pageTotal;
} else {
return 1;
}
} else {
return false;
}
}
function makePaginationURL($preURL, $pageTotal, $selected=0, $linkAttr=0, $selectedAttr=0) {
if (!empty($preURL) && $pageTotal >= 1) {
$pageSeed = 1;
$passFlag = 0;
$regLink = '<a href="{url}&p={page}"';
if (is_array($linkAttr)) $regLink .= $this->setAttributes($linkAttr); //set attributes
$regLink .= '>{page}</a>';
$selLink = '<a href="{url}&p={page}"';
if (is_array($selectedAttr)) $selLink .= $this->setAttributes($selectedAttr); //set attributes
$selLink .= '>{page}</a>';
while($pageSeed <= $pageTotal) {
if ($pageSeed == $selected) {
$newPageLink = str_replace('{url}', $preURL, $selLink);
$newPageLink = str_replace('{page}', $pageSeed, $newPageLink);
} else {
$newPageLink = str_replace('{url}', $preURL, $regLink);
$newPageLink = str_replace('{page}', $pageSeed, $newPageLink);
}
if ($passFlag == 0) {
$passFlag = 1;
$linkStack = $newPageLink;
} else {
$linkStack .= ', ' . $newPageLink;
}
$pageSeed++;
}
return $linkStack;
} else {
return false;
}
}
function splitPageArrayStack($stackArray, $chunkSize) {
if (is_array($stackArray) && is_numeric($chunkSize)) {
return $multiArray = array_chunk($stackArray, $chunkSize);
} else {
return false;
}
}
}

Categories