scriptdevelop / meta-catalog-manager
Laravel package for Meta Marketing API — multi-account catalog management, product feeds, batch inventory, offers, diagnostics and localized catalogs.
Package info
github.com/djdang3r/meta-catalog-manager
pkg:composer/scriptdevelop/meta-catalog-manager
Requires
- php: ^8.2
- guzzlehttp/guzzle: ^7.0
- laravel/framework: ^12.0 || ^13.0
Requires (Dev)
- mockery/mockery: ^1.6
- orchestra/testbench: ^10.2
- phpunit/phpunit: ^12.1
README
Laravel package for the Meta Marketing API — complete multi-account catalog management: products, feeds, batch inventory updates, offers, diagnostics, localized catalogs and more.
Features
- Multi-account — multiple Meta Business Manager accounts, each with multiple catalogs
- Token encryption —
app_id,app_secret,access_tokenencrypted at rest using Laravel'sencrypt() - Product Feeds — primary, supplementary, and localized feeds (language / country / language+country)
- Batch API — real-time inventory updates, create/update/delete items, localized batch
- Inventory history — immutable audit log of every stock change (
meta_inventory_logs) - Offers API —
SALE,AUTOMATIC_AT_CHECKOUT,BUYER_APPLIED(coupons, Buy X Get Y, free shipping) - Diagnostics — catalog errors, event source issues, pixel/app DA checks
- Event Stats — pixel and app event metrics per catalog
- Generic Feed Files API — promotions, shipping profiles, navigation menu, ratings & reviews
- Commerce Merchant Settings — checkout config, merchant status, Korea FTC compliance
- Page-Owned Catalogs — create and list catalogs owned by a Facebook Page
- Override Details API — inspect localized overrides per product item
- Best practices compliance —
google_product_category,rich_text_description,product_type,internal_label - 17-file Spanish documentation included
Requirements
| Dependency | Version |
|---|---|
| PHP | ^8.2 |
| Laravel | ^12.0 or ^13.0 |
| Guzzle | ^7.0 |
Installation
composer require scriptdevelop/meta-catalog-manager
Run the install wizard
php artisan meta-catalog:install
The wizard will:
- Publish the configuration file to
config/meta-catalog.php - Optionally merge the
meta-cataloglog channel into yourconfig/logging.php - Optionally run the package migrations
Publish manually
# Configuration php artisan vendor:publish --tag=meta-catalog-config # Migrations php artisan vendor:publish --tag=meta-catalog-migrations # Logging channel php artisan vendor:publish --tag=meta-catalog-logging
Run migrations
php artisan migrate
Configuration
// config/meta-catalog.php 'api' => [ 'base_url' => env('META_CATALOG_API_URL', 'https://graph.facebook.com'), 'graph_version' => env('META_CATALOG_GRAPH_VERSION', 'v22.0'), 'timeout' => env('META_CATALOG_API_TIMEOUT', 30), 'retries' => env('META_CATALOG_API_RETRIES', 3), ],
Environment variables
META_CATALOG_API_URL=https://graph.facebook.com META_CATALOG_GRAPH_VERSION=v22.0 META_CATALOG_API_TIMEOUT=30 META_CATALOG_API_RETRIES=3 META_CATALOG_AUTO_MIGRATIONS=true META_CATALOG_LOG_CHANNEL=meta-catalog
Override models
You can swap any model for your own extended class:
// config/meta-catalog.php 'models' => [ 'meta_business_account' => \App\Models\MyMetaBusinessAccount::class, 'meta_catalog' => \App\Models\MyMetaCatalog::class, // ... ],
Quick Start
Facade
use ScriptDevelop\MetaCatalogManager\Facades\MetaCatalog; // With context account MetaCatalog::forAccount($account)->catalog()->syncFromApi(); // Direct access MetaCatalog::account()->create([...]); MetaCatalog::catalog()->syncFromApi($account);
Services
AccountService
// Create an account $account = MetaCatalog::account()->create([ 'name' => 'My Business', 'meta_business_id' => '123456789', 'app_id' => 'APP_ID', // stored encrypted 'app_secret' => 'APP_SECRET', // stored encrypted 'access_token' => 'EAABwz...', // stored encrypted ]); // Find / list $account = MetaCatalog::account()->find($ulid); $account = MetaCatalog::account()->findByMetaBusinessId('123456789'); $accounts = MetaCatalog::account()->all();
CatalogService
// Sync catalogs from Meta API to local DB $catalogs = MetaCatalog::catalog()->syncFromApi($account); // Create a catalog $catalog = MetaCatalog::catalog()->create($account, [ 'name' => 'My Store Catalog', 'vertical' => 'commerce', ]); // Create a Page-Owned catalog $catalog = MetaCatalog::catalog()->createForPage($account, $pageId, [ 'name' => 'Page Catalog', ]);
ProductService
// Sync all products (auto-pagination) $count = MetaCatalog::product()->syncFromApi($catalog); // Single product operations MetaCatalog::product()->createSingle($catalog, [ 'retailer_id' => 'SKU-001', 'title' => 'Blue T-Shirt', 'price' => '19.99 USD', 'link' => 'https://mystore.com/t-shirt', 'image_link' => 'https://mystore.com/t-shirt.jpg', 'availability'=> 'in stock', 'condition' => 'new', 'brand' => 'MyBrand', 'google_product_category' => 'Apparel & Accessories > Clothing > Shirts & Tops', ]); // Get override details (localized data) $overrides = MetaCatalog::product()->getOverrideDetails( $productItemId, $account, keys: ['US', 'es_XX'], type: FeedOverrideType::COUNTRY );
FeedService
// Create a primary feed with daily schedule $feed = MetaCatalog::feed()->create($catalog, [ 'name' => 'Main Product Feed', 'schedule' => [ 'interval' => 'DAILY', 'url' => 'https://mystore.com/feed.csv', 'hour' => 2, ], ]); // Upload from URL (one-time) MetaCatalog::feed()->uploadFromUrl($feed, 'https://mystore.com/feed.csv'); // Upload from local file MetaCatalog::feed()->uploadFromFile($feed, '/path/to/feed.csv'); // Supplementary feed (updates without deleting items) MetaCatalog::feed()->createSupplementaryFeed($catalog, [ 'name' => 'Price Updates', 'primary_feed_ids' => ['1234567890'], 'schedule' => ['interval' => 'HOURLY', 'url' => 'https://...'], ]); // Localized feeds MetaCatalog::feed()->createLanguageFeed($catalog, 'Language Feed ES/FR'); MetaCatalog::feed()->createCountryFeed($catalog, 'Country Feed US/UK'); MetaCatalog::feed()->createLanguageAndCountryFeed($catalog, 'Locale Feed fr|CA'); // Error reporting $errors = MetaCatalog::feed()->getUploadErrors($upload); MetaCatalog::feed()->requestErrorReport($upload); $report = MetaCatalog::feed()->getErrorReport($upload);
BatchService
// Real-time inventory update (async) $batch = MetaCatalog::batch()->updateItems($catalog, [ ['retailer_id' => 'SKU-001', 'quantity_to_sell_on_facebook' => 50], ['retailer_id' => 'SKU-002', 'quantity_to_sell_on_facebook' => 0], ]); // Check status $status = MetaCatalog::batch()->checkStatus($catalog, $batch->handle); // Create items MetaCatalog::batch()->createItems($catalog, $items); // Delete items MetaCatalog::batch()->deleteItems($catalog, ['SKU-001', 'SKU-002']); // Localized batch MetaCatalog::batch()->sendLocalizedBatch($catalog, $localizedItems);
InventoryService
// Update a single item's stock MetaCatalog::inventory()->updateSingle( $catalogItem, 25, InventoryChangeSource::MANUAL, 'Manual stock adjustment' ); // Batch update via Meta Batch API MetaCatalog::inventory()->updateBatch($catalog, [ ['retailer_id' => 'SKU-001', 'quantity' => 10], ['retailer_id' => 'SKU-002', 'quantity' => 0], ]); // History and reporting $history = MetaCatalog::inventory()->getHistory($catalogItem); $last = MetaCatalog::inventory()->getLastLog($catalogItem); $lowStock = MetaCatalog::inventory()->getLowStock($catalog, threshold: 5); $outOfStock = MetaCatalog::inventory()->getOutOfStock($catalog);
ProductSetService
$set = MetaCatalog::productSet()->create($catalog, [ 'name' => 'Summer Sale', 'filter' => ['availability' => ['eq' => 'in stock']], ]); MetaCatalog::productSet()->syncFromApi($catalog);
DiagnosticsService
// Catalog-level diagnostics $diagnostics = MetaCatalog::diagnostics()->fetchFromApi($catalog); MetaCatalog::diagnostics()->syncFromApi($catalog); // Event source issues $issues = MetaCatalog::diagnostics()->getEventSourceIssues($catalog, $account); $hasCritical = MetaCatalog::diagnostics()->hasCriticalEventSourceIssues($catalog, $account);
EventStatsService
$stats = MetaCatalog::eventStats()->fetchFromApi($catalog); MetaCatalog::eventStats()->syncFromApi($catalog);
OfferService
$offer = MetaCatalog::offer()->createOffer($catalog, [ 'offer_id' => 'SUMMER20', 'title' => 'Summer Sale 20% Off', 'application_type' => OfferApplicationType::SALE->value, 'value_type' => 'PERCENTAGE', 'percent_off' => 20, 'start_date_time' => '2025-06-01T00:00:00', 'end_date_time' => '2025-08-31T23:59:59', ]); $activeSales = MetaCatalog::offer()->getActiveSales($catalog); $activeCoupons = MetaCatalog::offer()->getActiveCoupons($catalog);
GenericFeedService
// Upload shipping profiles MetaCatalog::genericFeed()->uploadShippingProfiles( $account, $commercePartnerIntegrationId, '/path/to/shipping.csv' ); // Upload promotions MetaCatalog::genericFeed()->uploadPromotions( $account, $commercePartnerIntegrationId, '/path/to/promotions.csv' ); // Upload ratings & reviews MetaCatalog::genericFeed()->uploadRatingsAndReviews($catalog, '/path/to/reviews.csv');
MerchantSettingsService
$settings = MetaCatalog::merchantSettings()->get($account, $commerceMerchantSettingsId); MetaCatalog::merchantSettings()->enable($account, $commerceMerchantSettingsId); MetaCatalog::merchantSettings()->setCheckoutConfig( $account, $commerceMerchantSettingsId, checkoutUrl: 'https://mystore.com/checkout', countryCode: 'US' );
Localized Catalogs
Support for language, country, and language+country override feeds:
use ScriptDevelop\MetaCatalogManager\Enums\FeedOverrideType; // Language feed (translations: title, description) MetaCatalog::feed()->createLanguageFeed($catalog, 'Language Feed ES/FR', [ 'interval' => 'DAILY', 'url' => 'https://mystore.com/feeds/languages.csv', 'hour' => 22, ]); // Country feed (prices, availability, links by country) MetaCatalog::feed()->createCountryFeed($catalog, 'Country Feed US/UK/AR', [ 'interval' => 'DAILY', 'url' => 'https://mystore.com/feeds/countries.csv', 'hour' => 3, ]); // Language+country feed (advanced: fr_XX|CA, fr_XX|US) MetaCatalog::feed()->createLanguageAndCountryFeed($catalog, 'Locale Feed', [ 'interval' => 'DAILY', 'url' => 'https://mystore.com/feeds/locales.tsv', 'hour' => 4, ]); // Inspect overrides for a specific product $overrides = MetaCatalog::product()->getOverrideDetails($productItemId, $account);
Priority order: language_and_country → language → country → main catalog.
Database Schema
| Table | Description |
|---|---|
meta_business_accounts |
Accounts with encrypted tokens |
meta_catalogs |
Product catalogs |
meta_product_feeds |
Primary, supplementary, and localized feeds |
meta_product_feed_uploads |
Upload sessions and error tracking |
meta_catalog_items |
Product items with full field set |
meta_product_sets |
Product sets with filter JSON |
meta_batch_requests |
Batch API requests and status |
meta_catalog_diagnostics |
Catalog error cache |
meta_event_sources |
Pixels and apps linked to catalogs |
meta_event_stats |
Event metric cache |
meta_inventory_logs |
Immutable inventory change audit log |
meta_catalog_offers |
Offers (sale, coupon, Buy X Get Y) |
meta_generic_feeds |
Generic feed files (shipping, promotions, etc.) |
Available Enums
| Enum | Values |
|---|---|
AccountStatus |
ACTIVE, DISCONNECTED, REMOVED |
CatalogVertical |
commerce, hotels, flights, destinations, vehicles, home_listings |
CatalogItemType |
PRODUCT_ITEM, VEHICLE, HOTEL, FLIGHT, DESTINATION, HOME_LISTING, VEHICLE_OFFER |
ItemAvailability |
in stock, out of stock, preorder, available for order, discontinued |
ItemCondition |
new, refurbished, used |
FeedIngestionSourceType |
PRIMARY_FEED, SUPPLEMENTARY_FEED |
FeedOverrideType |
language, country, language_and_country |
FeedFormat |
csv, tsv, rss_xml, atom_xml, google_sheets |
FeedScheduleType |
HOURLY, DAILY, WEEKLY |
BatchRequestStatus |
IN_PROGRESS, FINISHED, ERROR |
InventoryChangeSource |
feed_upload, batch_api, manual, system |
OfferApplicationType |
SALE, AUTOMATIC_AT_CHECKOUT, BUYER_APPLIED |
OfferValueType |
FIXED_AMOUNT, PERCENTAGE |
GenericFeedType |
PROMOTIONS, SHIPPING_PROFILES, NAVIGATION_MENU, PRODUCT_RATINGS_AND_REVIEWS |
EventSourceIssueType |
PIXEL_MISSING_SIGNAL, PIXEL_NOT_MAPPED, LOW_MATCH_RATE, ... |
Documentation
Full Spanish documentation is available in documentation/es/:
- Instalación
- Configuración
- Cuentas de Negocio
- Catálogos
- Productos
- Inventario
- Feeds
- Batch API
- Conjuntos de Productos
- Diagnósticos
- Ofertas
- Diagnósticos Avanzados
- Microdatos
- Calificaciones y Opiniones
- Feeds Genéricos
- Merchant Settings
- Catálogos Localizados
Changelog
See CHANGELOG.md for release history.
License
MIT © Wilfredo Perilla