Skip to content

Scraper-APIs/g2-reviews-scraper-php

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tests PHP Version License

A PHP library for scraping product reviews from G2.com using the Apify G2 Reviews Scraper. Returns fully typed DTOs for easy integration into your application. Safe, reliable and scalable.

Installation

composer require scraper-apis/g2-reviews-scraper

Requirements

Quick Start

use G2ReviewsScraper\Client;

$client = new Client('YOUR_APIFY_TOKEN');

// Scrape reviews for a product
$reviews = $client->scrape('https://www.g2.com/products/notion/reviews');

foreach ($reviews as $review) {
    echo $review->title . ' - ' . $review->starRating . '' . PHP_EOL;
}

Usage

Basic Review Scraping

$reviews = $client->scrape(
    url: 'https://www.g2.com/products/notion/reviews',
    limit: 100
);

Sort by Rating

use G2ReviewsScraper\SortOrder;

// Get lowest-rated reviews first (for competitor analysis)
$reviews = $client->scrape(
    url: 'https://www.g2.com/products/jira/reviews',
    limit: 500,
    sortOrder: SortOrder::LowestRated
);

Filter by Star Rating

// Only 1-2 star reviews
$reviews = $client->scrape(
    url: 'https://www.g2.com/products/salesforce/reviews',
    limit: 200,
    starRatings: ['1', '2']
);

Search Reviews

// Reviews mentioning "integration"
$reviews = $client->scrape(
    url: 'https://www.g2.com/products/hubspot/reviews',
    limit: 100,
    searchQuery: 'integration'
);

Get Pros/Cons Summary

// Scrape reviews + AI-generated pros/cons summary
$result = $client->scrapeWithProsCons(
    url: 'https://www.g2.com/products/slack/reviews',
    limit: 500
);

// Access reviews
foreach ($result['reviews'] as $review) {
    echo $review->title . PHP_EOL;
}

// Access AI summary
$prosCons = $result['prosCons'];
echo "Product: {$prosCons->productName}" . PHP_EOL;
echo "Average Rating: {$prosCons->productAverageRating}" . PHP_EOL;

foreach ($prosCons->aiPros as $pro) {
    echo "PRO: {$pro->text} ({$pro->mentions} mentions)" . PHP_EOL;
}

foreach ($prosCons->aiCons as $con) {
    echo "CON: {$con->text} ({$con->mentions} mentions)" . PHP_EOL;
}

Working with Review Data

foreach ($reviews as $review) {
    // Basic info
    echo $review->title;
    echo $review->starRating;           // e.g., 5.0
    echo $review->date;                 // e.g., "2026-01-15"

    // Reviewer details
    echo $review->reviewerName;         // e.g., "John Smith"
    echo $review->reviewerTitle;        // e.g., "Software Engineer"
    echo $review->getCompanyInfo();     // e.g., "Mid-Market (51-1000 emp.) | Used for 2+ years"

    // Review content (pros | cons | recommendations)
    echo $review->text;

    // Verification badges
    if ($review->hasValidatedReviewer()) {
        echo "Verified via: {$review->validatedMethod}"; // "LinkedIn" or "Business Email"
    }
    if ($review->isCurrentUser()) {
        echo "Verified current user";
    }
    if ($review->incentivized) {
        echo "Incentivized review";
    }

    // LLM-ready markdown (for RAG pipelines)
    echo $review->markdownContent;
}

Filtering Results

// Filter for validated reviewers only
$validated = array_filter(
    $reviews,
    fn ($r) => $r->hasValidatedReviewer()
);

// Filter for current users only
$currentUsers = array_filter(
    $reviews,
    fn ($r) => $r->isCurrentUser()
);

// Filter by rating
$fiveStarReviews = array_filter(
    $reviews,
    fn ($r) => $r->starRating === 5.0
);

// Filter non-incentivized reviews
$organic = array_filter(
    $reviews,
    fn ($r) => !$r->incentivized
);

DTOs

Review

Property Type Description
reviewId string Unique review identifier
productName string Product name
productSlug string Product URL slug
title ?string Review headline
starRating ?float Rating (1.0-5.0)
reviewerName ?string Reviewer's name
reviewerTitle ?string Reviewer's job title
date ?string Review date (YYYY-MM-DD)
text ?string Full review text (pros | cons | recommendations)
reviewerInfo ?string[] Company size, usage duration
reviewerAvatarUrl ?string Avatar image URL
reviewerMonogram ?string Avatar initials
validatedReviewer bool Reviewer identity verified
validatedMethod ?string "LinkedIn" or "Business Email"
verifiedCurrentUser bool Verified current product user
reviewSource string Review source (e.g., "Organic")
incentivized bool Incentivized review flag
markdownContent ?string LLM-ready markdown format

ProsCons

Property Type Description
productName string Product name
productSlug string Product URL slug
productId ?string G2 product ID
productUuid ?string G2 product UUID
vendorId ?string Vendor ID
vendorName ?string Vendor company name
productType ?string Product type
productCategory ?string Primary category
productAverageRating ?float Overall rating
productImageUrl ?string Product logo URL
productCategories ?string[] All product categories
aiPros AiSummaryItem[] AI-generated pro points
aiCons AiSummaryItem[] AI-generated con points
topPros ProsConsCategory[] Top pro categories with samples
topCons ProsConsCategory[] Top con categories with samples

AiSummaryItem

Property Type Description
text string Summary text
keyword ?string Key term
mentions int Number of mentions

ProsConsCategory

Property Type Description
name string Category name (e.g., "Ease of Use")
summary string Category summary
keyword ?string Key term
mentions int Total mentions
sampleReviews SampleReview[] Sample reviews (max 2)

Sort Orders

Enum Value Description
SortOrder::MostRecent most_recent Newest reviews first
SortOrder::MostHelpful most_helpful Most upvoted reviews first
SortOrder::LowestRated lowest_rated 1-star reviews first
SortOrder::HighestRated highest_rated 5-star reviews first

Error Handling

use G2ReviewsScraper\Exception\ApiException;
use G2ReviewsScraper\Exception\RateLimitException;
use G2ReviewsScraper\Exception\InvalidUrlException;

try {
    $reviews = $client->scrape($url);
} catch (InvalidUrlException $e) {
    // Invalid G2 product URL
    echo $e->getMessage();
} catch (RateLimitException $e) {
    // Handle rate limiting
    sleep($e->retryAfter);
} catch (ApiException $e) {
    // Handle other API errors
    echo $e->getMessage();
}

Deduplication

When scraping multiple products, use reviewId as the unique key:

$allReviews = [];

$products = ['notion', 'asana', 'monday-com'];
foreach ($products as $product) {
    $url = "https://www.g2.com/products/{$product}/reviews";
    foreach ($client->scrape($url, limit: 100) as $review) {
        $allReviews[$review->reviewId] = $review;
    }
}

// $allReviews now contains unique reviews only

Use Cases

Competitor Analysis

// Get negative reviews for competitor analysis
$reviews = $client->scrape(
    url: 'https://www.g2.com/products/competitor-product/reviews',
    limit: 500,
    sortOrder: SortOrder::LowestRated,
    starRatings: ['1', '2', '3']
);

// Analyze common complaints
$complaints = [];
foreach ($reviews as $review) {
    $complaints[] = $review->text;
}

Sentiment Monitoring

// Track reviews over time
$result = $client->scrapeWithProsCons(
    url: 'https://www.g2.com/products/your-product/reviews',
    limit: 1000,
    sortOrder: SortOrder::MostRecent
);

$prosCons = $result['prosCons'];
$proMentions = $prosCons->getTotalProMentions();
$conMentions = $prosCons->getTotalConMentions();
$sentimentRatio = $proMentions / max(1, $conMentions);

RAG Pipeline Integration

// Export reviews for LLM ingestion
foreach ($reviews as $review) {
    // Use pre-formatted markdown
    $document = $review->markdownContent;

    // Or build custom format
    $metadata = [
        'reviewId' => $review->reviewId,
        'product' => $review->productName,
        'rating' => $review->starRating,
        'validated' => $review->hasValidatedReviewer(),
    ];

    // Store in vector database
    $vectorDb->insert($document, $metadata);
}

License

MIT

About

G2 Review Scraper using Apify

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages