PHPackages                             snapsearch/snapsearch-client-php - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Search &amp; Filtering](/categories/search)
4. /
5. snapsearch/snapsearch-client-php

ActiveLibrary[Search &amp; Filtering](/categories/search)

snapsearch/snapsearch-client-php
================================

PHP HTTP Client Middleware Libraries for SnapSearch. Search engine optimisation for single page applications.

1.2.2(11y ago)7395MITPHPPHP &gt;=5.3.3

Since Nov 19Pushed 11y ago6 watchersCompare

[ Source](https://github.com/SnapSearch/SnapSearch-Client-PHP)[ Packagist](https://packagist.org/packages/snapsearch/snapsearch-client-php)[ Docs](https://github.com/SnapSearch/SnapSearch-Client-PHP)[ RSS](/packages/snapsearch-snapsearch-client-php/feed)WikiDiscussions master Synced 2mo ago

READMEChangelogDependencies (5)Versions (8)Used By (0)

Snapsearch Client PHP
=====================

[](#snapsearch-client-php)

[![Build Status](https://camo.githubusercontent.com/ea30d97eeac708f8d5a2caffffe36c73461c33013e2415158c6ce7bfbfff5adb/68747470733a2f2f7472617669732d63692e6f72672f536e61705365617263682f536e61705365617263682d436c69656e742d5048502e706e673f6272616e63683d6d6173746572)](https://travis-ci.org/SnapSearch/SnapSearch-Client-PHP)

Snapsearch Client PHP is PHP based framework agnostic HTTP client library for SnapSearch ().

- It's PSR-0 compliant.
- Compatible with [Stack PHP](http://stackphp.com/) or HTTP Kernel frameworks.
- Works on HHVM. (Check Travis!)

Snapsearch is a search engine optimisation (SEO) and robot proxy for complex front-end javascript &amp; AJAX enabled (potentially realtime) HTML5 web applications.

Search engines like Google's crawler and dumb HTTP clients such as Facebook's image extraction robot cannot execute complex javascript applications. Complex javascript applications include websites that utilise AngularJS, EmberJS, KnockoutJS, Dojo, Backbone.js, Ext.js, jQuery, JavascriptMVC, Meteor, SailsJS, Derby, RequireJS and much more. Basically any website that utilises javascript in order to bring in content and resources asynchronously after the page has been loaded, or utilises javascript to manipulate the page's content while the user is viewing them such as animation.

Snapsearch intercepts any requests made by search engines or robots and sends its own javascript enabled robot to extract your page's content and creates a cached snapshot. This snapshot is then passed through your own web application back to the search engine, robot or browser.

Snapsearch's robot is an automated load balanced Firefox browser. This Firefox browser is kept up to date with the nightly versions, so we'll always be able to serve the latest in HTML5 technology. Our load balancer ensures your requests won't be hampered by other user's requests.

For more details on how this works and the benefits of usage see

SnapSearch provides similar libraries in other languages:

Installation
------------

[](#installation)

Requires 5.3.3 or above and Curl extension.

**Composer**

Add this to your `composer.json`

```
"snapsearch/snapsearch-client-php": "~1.2"

```

Then run `composer install` or `composer update`.

**Native**

Just extract repository into your library location. Then use your own PSR-0 autoloader to autoload the classes inside `src/SnapSearchClientPHP/`.

You can also use the supplied autoloader. First clone this project to your desired location, then write:

```
require_once('SnapSearch-Client-PHP/src/SnapSearchClientPHP/Bootstrap.php');
\SnapSearchClientPHP\Bootstrap::register();
```

If you don't want to use an autoloader, just require all the classes inside `src/SnapSearchClientPHP/` except `Bootstrap.php`.

Note you will have to install the dependencies and autoload them manually as well. Look into `composer.json` file and find the dependencies in the `"require"` section.

Don't forget about the `resources/` folder containing the necessary resources for this library to work.

Usage
-----

[](#usage)

SnapSearchClientPHP should be best started at the entry point your application. This could be inside a front controller, bootstrapping process, IOC container, or middleware. For a single page application, your entry point would be the code that first presents the initial HTML page.

For full documentation on the API and API request parameters see:

**By the way, you need to blacklist non-html resources such as `sitemap.xml`. This is explained in **

\###Basic Usage

```
$client = new \SnapSearchClientPHP\Client('email', 'key');
$detector = new \SnapSearchClientPHP\Detector;
$interceptor = new \SnapSearchClientPHP\Interceptor($client, $detector);

//exceptions should be ignored in production, but during development you can check it for validation errors
try{

    $response = $interceptor->intercept();

}catch(SnapSearchClientPHP\SnapSearchException $e){}

if($response){

    //this request is from a robot

    //status code
    header(' ', true, $response['status']); //as of PHP 5.4, you can use http_response_code($response['status']);

    //the complete $response['headers'] is not returned to the search engine due to potential content or transfer encoding issues, except for the potential location header, which is used when there is an HTTP redirect
    if(!empty($response['headers'])){
        foreach($response['headers'] as $header){
            if($header['name'] == 'Location'){
                header($header['name'] . ': ' . $header['value']);
            }
        }
    }

    //content
    echo $response['html'];

}else{

    //this request is not from a robot
    //continue with normal operations...

}
```

Here's an example `$response` variable (not all variables are available, you need to check the request parameters):

```
$response = [
    'cache'             => true/false,
    'callbackResult'    => '',
    'date'              => 1390382314,
    'headers'           => [
        [
            'name'  => 'Content-Type',
            'value' => 'text/html'
        ]
    ],
    'html'              => '',
    'message'           => 'Success/Failed/Validation Errors',
    'pageErrors'        => [
        [
            'error'   => 'Error: document.querySelector(...) is null',
            'trace'   => [
                [
                    'file'      => 'filename',
                    'function'  => 'anonymous',
                    'line'      => '41',
                    'sourceURL' => 'urltofile'
                ]
            ]
        ]
    ],
    'screenshot'        => 'BASE64 ENCODED IMAGE CONTENT',
    'status'            => 200
]
```

\###Advanced Usage

```
$request_parameters = array(
    //add your API request parameters if you have any...
);

$blacklisted_routes = array(
    //add your black listed routes if you have any...
);

$whitelisted_routes = array(
    //add your white listed routes if you have any...
);

$check_file_extensions = //if you wish for SnapSearchClient to check if the URL leads to a static file, switch this on to a boolean true, however this is expensive and time consuming, so it's better to use black listed or white listed routes

$symfony_http_request_object = //get the Symfony\Component\HttpFoundation\Request

$robot_json_path = //if you have a custom robots.json you can choose to use that instead, use the absolute path

$extensions_json_path = //if you have a custom extensions.json you can choose hat insead, use the absolute path

$client = new \SnapSearchClientPHP\Client('email', 'key', $request_parameters);

$detector = new \SnapSearchClientPHP\Detector(
    $blacklisted_routes,
    $whitelisted_routes,
    $check_file_extensions,
    $symfony_http_request_object,
    $robot_json_path,
    $extensions_json_path
);

//robots can be direct accessed and manipulated
$detector->robots['match'][] = 'my_custom_bot_to_be_matched';
$detector->robots['ignore'][] = 'my_ignored_robot';

//extensions can as well, add to 'generic' or 'php'
$detector->extensions['php'][] = 'validextension';

$interceptor = new \SnapSearchClientPHP\Interceptor($client, $detector);

//your custom cache driver
$cache = new YourCustomClientSideCacheDriver;

//the before_intercept callback is called after the Detector has detected a search engine robot
//if this callback returns an array, the array will be used as the $response to $interceptor->intercept();
//use it for client side caching in order to have millisecond responses to search engines
//the after_intercept callback can be used to store the snapshot from SnapSearch as a client side cached resource
//this is of course optional as SnapSearch caches your snapshot as well!
$interceptor->before_intercept(function($url) use ($cache){

    //get cache from redis/filesystem..etc
    //returned value should array if successful or boolean false if cache did not exist
    return $cache->get($url);

})->after_intercept(function($url, $response) use ($cache){

    //the cached time should be less then the cached time you passed to SnapSearch, we recommend half the SnapSearch cachetime
    $time = '12hrs';
    $cache->store($url, $response, $time);

});

//exceptions should be ignored in production, but during development you can check it for validation errors
try{

    $response = $interceptor->intercept();

}catch(SnapSearchClientPHP\SnapSearchException $e){}

if($response){

    //this request is from a robot

    //status code
    header(' ', true, $response['status']); //as of PHP 5.4, you can use http_response_code($response['status']);

    //the complete $response['headers'] is not returned to the search engine due to potential content or transfer encoding issues, except for the potential location header, which is used when there is an HTTP redirect
    if(!empty($response['headers'])){
        foreach($response['headers'] as $header){
            if(strtolower($header['name']) == 'location'){
                header($header['name'] . ': ' . $header['value']);
            }
        }
    }

    //content
    echo $response['html'];

}else{

    //this request is not from a robot
    //continue with normal operations...

}
```

\###Stack PHP Usage

Stack PHP is a HTTP Kernel Middleware Layer Framework for PHP similar to Ruby Rack or Node Connect. The below example uses PHP 5.4 code.

```
$app =  //HTTP Kernel core controller

$stack = (new \Stack\Builder)->push(
    '\SnapSearchClientPHP\StackInterceptor',
    new Interceptor(
        new Client('email', 'key'),
        new Detector
    )->before_intercept(function($url){
        //before interception callback (optional and chainable)
    })->after_intercept(function($url, $response){
        //after interception callback (optional and chainable)
    }),
    function(array $response){

        //this callback is completely optional, it allows you to customise your response
        //the $response array comes from SnapSearch and contains [(string) 'status', (array) 'headers', (string) 'html']

        //remember $response['headers'] is in this format:
        //[
        //    [
        //        'name'  => 'Location',
        //        'value' => 'http://redirect.com/'
        //    ]
        //]
        //it's an array of arrays which contain name and value properties

        //it's recommended to not pass through all of the headers, due to possible encoding problems
        //your server will already output the necessary headers anyway
        //however we are passing through the location header if it exists
        $headers = array_filter($response['headers'], function($header){
            if(strtolower($header['name']) == 'location'){
                return true;
            }
            return false;
        });

        return [
            'status'    => $response['status'],
            'headers'   => $headers,
            'html'      => $response['html']
        ];

    },
    function($exception, $request){

        //this is the exception callback and it's completely optional
        //it will only be called if a SnapSearchException is raised
        //which only happens if SnapSearch's servers are temporarily offline
        //if there is an exception, this middleware will simply pass to the next layer
        //if you want to stop and inspect or log the actual exception, this is where you can do it

    }
);

$app = $stack->resolve($app);

$request  = Request::createFromGlobals();
$response = $app->handle($request)->send();
$app->terminate($request, $response);
//or just do this if you have Stack\run
//\Stack\run($app);
```

The `$check_file_extensions` boolean for the Detector constructor is available for applications that might serve static files. Usually the HTTP server serves up static files and these requests never get proxied to the application, this is why by default this boolean is false. However in cases where it does serve up static files, you can switch this to true to prevent static files routes from being intercepted.

It can be more efficient or easier to blacklist routes which lead to static files instead. This has the advantage of allowing you to prevent routes that go to binary resources which may not end in specific file extensions. Such as streaming audio/video.

SnapSearchClientPHP can of course be used in other areas such as javascript enhanced scraping, so it doesn't force you to put it at the entry point if you're using it for other purposes. In that case just use the `SnapSearchPHP\Client` to send requests to the SnapSearch API.

Proxies
-------

[](#proxies)

SnapSearch-Client-PHP uses the Symfony HTTP Foundation Request Object as an abstraction of the HTTP request. This allows you considerable flexibility and constructing the HTTP request especially when you're behind a reverse proxy such as a load balancer. If you are behind a reverse proxy, certain information such as the request protocol is not where it is normally. You can configure the Symfony HTTP Foundation Request Object to handle these edge cases, and simply pass your instance into the Detector. See this for more information: [http://symfony.com/doc/current/components/http\_foundation/trusting\_proxies.html](http://symfony.com/doc/current/components/http_foundation/trusting_proxies.html)

Development
-----------

[](#development)

Install/update dependencies with composer:

```
composer update
```

Make your changes, synchronise, then create a new tag:

```
git tag MAJOR.MINOR.PATCH
git push
git push --tags
```

Packagist is integrated in the Github Service Hooks, it will automatically release the new package.

Tests
-----

[](#tests)

Unit tests are written using Codeception. Codeception has already been bootstrapped (`codecept bootstrap`). To run tests use `codecept run` or `codecept run --debug` for debug messages. If you change the Codeception configuration files or add extra functions to the helpers make sure to run `codecept build` so that the settings take effect.

###  Health Score

30

—

LowBetter than 65% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity15

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity63

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~88 days

Recently: every ~115 days

Total

7

Last Release

4028d ago

Major Versions

0.0.2 → 1.0.02014-01-24

### Community

Maintainers

![](https://www.gravatar.com/avatar/6cac1bf212b88210ea171320885e262121d33d0f8a11b12d102d03eeee3005d8?d=identicon)[CMCDragonkai](/maintainers/CMCDragonkai)

---

Top Contributors

[![CMCDragonkai](https://avatars.githubusercontent.com/u/640797?v=4)](https://github.com/CMCDragonkai "CMCDragonkai (111 commits)")

---

Tags

javascriptajaxextjsseobackboneemberdojoangularsearch engine optimisationknockout

###  Code Quality

TestsCodeception

### Embed Badge

![Health badge](/badges/snapsearch-snapsearch-client-php/health.svg)

```
[![Health](https://phpackages.com/badges/snapsearch-snapsearch-client-php/health.svg)](https://phpackages.com/packages/snapsearch-snapsearch-client-php)
```

###  Alternatives

[wilr/silverstripe-googlesitemaps

SilverStripe support for the Google Sitemaps XML, enabling Google and other search engines to see all urls on your site. This helps your SilverStripe website rank well in search engines, and to encourage the information on your site to be discovered quickly.

75626.0k28](/packages/wilr-silverstripe-googlesitemaps)[quinninteractive/silverstripe-seo

An all-in-one SEO module for SilverStripe

3328.2k](/packages/quinninteractive-silverstripe-seo)[dneustadt/csrf-cookie-bundle

CSRF protection cookie for use with XHR

1379.2k1](/packages/dneustadt-csrf-cookie-bundle)[ymigval/laravel-indexnow

Laravel Service Library for notifying search engines about the latest content changes on their URLs using IndexNow.

3410.2k](/packages/ymigval-laravel-indexnow)[keygenqt/yii2-autocomplete-ajax

A simple way to search model id of the attributes model

1015.8k](/packages/keygenqt-yii2-autocomplete-ajax)[mediamonks/crawler

Crawl your own website with various clients for SEO and indexing purposes.

211.1k1](/packages/mediamonks-crawler)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
