scraper-apis / g2-reviews-scraper
PHP Scraper library for fetching product reviews from G2.com using an Apify actor
Package info
github.com/Scraper-APIs/g2-reviews-scraper-php
pkg:composer/scraper-apis/g2-reviews-scraper
dev-master
2026-02-12 08:59 UTC
Requires
- php: ^8.3
- guzzlehttp/guzzle: ^7.0
Requires (Dev)
- laravel/pint: ^1.0
- pestphp/pest: ^4.0
- phpstan/phpstan: ^1.0
This package is auto-updated.
Last update: 2026-02-12 09:05:20 UTC
README
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
- PHP 8.3+
- Apify API token (get one here)
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