descom / descommarket-feeds
DescomMarket Feeds
Requires
- php: ^8.4
- descom/descommarket_common: ^1.8
- descom/pipeline: ^2.4
- google/apiclient: ^2.12.1
- google/shopping-merchant-datasources: ^1.3
- google/shopping-merchant-products: ^1.7
- illuminate/console: *
- illuminate/database: *
- laravel/framework: ^12.0|^13.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.75
- guzzlehttp/guzzle: ^7.8
- larastan/larastan: ^3.0
- orchestra/testbench: ^10.0|^11.0
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^11.5
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-master
- 1.19
- 1.18.0
- 1.17.1
- 1.17.0
- 1.16.0
- 1.15.0
- 1.14.1
- 1.14.0
- 1.13.0
- 1.12.0
- 1.11.0
- 1.10.0
- 1.9.1
- 1.9.0
- 1.8.1
- 1.8.0
- 1.7.0
- 1.6.0
- 1.5.1
- 1.5.0
- 1.4.1
- 1.4.0
- 1.3.1
- 1.3.0
- 1.2.1
- 1.2.0
- 1.1.2
- 1.1.1
- 1.1.0
- 1.0.0
- 0.0.6
- 0.0.5
- 0.0.4
- 0.0.3
- 0.0.2
- 0.0.1
- dev-merchant_api_migration
- dev-product_noindex
- dev-meta
- dev-update_gtin_in_gm
- dev-gm_product_expiration_renew
- dev-competitiveness-service
- dev-cron-command
- dev-url-index-command
This package is auto-updated.
Last update: 2026-09-10 09:08:58 UTC
README
Add to .env
GOOGLE_API_CREDENTIALS_PATH=
GOOGLE_MERCHANT_ID=
GOOGLE_MERCHANT_DATA_SOURCE=
GOOGLE_MERCHANT_DATA_SOURCE_NAME=
GOOGLE_MERCHANT_QUEUE_CONNECTION=sync
GOOGLE_MERCHANT_QUEUE_TRIES=10
#Optional, only if you want to override the default values in the config file
GOOGLE_MERCHANT_FEED_LABEL=ES
GOOGLE_MERCHANT_CONTENT_LANGUAGE=es
GOOGLE_MERCHANT_TRANSPORT=rest
GOOGLE_INDEX_ENABLED=
GOOGLE_INDEX_QUEUE_CONNECTION=sync
GOOGLE_INDEX_QUEUE_TRIES=10
Add config
php artisan vendor:publish --provider="DescomMarket\Feeds\DescomMarketFeedsServiceProvider"
Google Merchant
Products go to Merchant Center through the Merchant API. Google sunset the Content API for Shopping on August 18, 2026.
Set up an account in this order:
- Give the service account admin access to the merchant account, which needs a verified website.
- Register the GCP project:
dm360:google:merchant:developer-registration --register. - Put the data source id in
GOOGLE_MERCHANT_DATA_SOURCE.
Then the package works on its own, in the google_merchant queue:
use DescomMarket\Common\Events\Catalog\Products\ProductPublished; // insert use DescomMarket\Common\Events\Catalog\Products\ProductUpdated; // insert (overwrites) use DescomMarket\Common\Events\Catalog\Products\ProductUnpublished; // delete
Developer registration
The Merchant API rejects every call, reads included, until the GCP project used to
authenticate is registered with the merchant account: a 401 carrying
GCP_NOT_REGISTERED. There is no UI for it.
php artisan dm360:google:merchant:developer-registration # check php artisan dm360:google:merchant:developer-registration --register # register
The check exits with a failure code when no project is registered. Google then needs about five minutes before it accepts calls.
It only registers once. A second registerGcp returns 409, so nothing can be
corrected that way afterwards: a botched registration has to be restarted.
What every account needs is at least one user holding the API developer role.
Removing the last one blocks API calls after a 30 day grace period. The role only
receives the notifications, so it stacks on whatever access the user already has: an
existing admin can take it, and a user who only holds it needs STANDARD or ADMIN on
top to do anything else. It lives in Access and services > People and access.
There are two ways to get there:
- Without a contact.
registerGcponly links the GCP project, and you grant the role to a user that already exists, in the Merchant Center UI. - With a contact,
--register --email=someone@example.com. Google invites that address and grants it the role, but the registration is only complete once the invitation is accepted, within 14 days. If the link expires, API calls stop and the registration has to be started over. The address must be a Google account and cannot be a service account, or the invitation can never be accepted.
unregisterGcp on the same resource undoes a registration. It is deliberately not wired
into the command.
Data source
The Merchant API cannot take a product without a data source. The package resolves one on the first call of each process:
- With
GOOGLE_MERCHANT_DATA_SOURCEset, that id is used and nothing is looked up. - Otherwise, the primary product data source whose display name matches
GOOGLE_MERCHANT_DATA_SOURCE_NAME, which is then required. It is created when missing, and two sources sharing that name fail instead of picking one.
Pin the id on any account that already sent products with the Content API. A product
is identified per account by contentLanguage~feedLabel~offerId, not per data source, so
sending it to another primary source does not duplicate it: it moves it — offer
stealing, in Google's words — and changes the rules and ownership that applied. Content
API sources stay compatible and show up as Content API in the UI, but their display
name is whatever Merchant Center gave them, so a name lookup may or may not land on the
right one: when it misses it creates a second source and moves the catalogue into it, one
product per call. Deletes send the data source too, so a wrong pin answers NOT_FOUND,
which the package reads as "already gone" while the product stays published.
Ids come from DataSourceService::list(), or from products.get on a product already
up, which reports the source it belongs to. Google generates them, they cannot be chosen.
GOOGLE_MERCHANT_FEED_LABEL and GOOGLE_MERCHANT_CONTENT_LANGUAGE are set on the data
source when it is created and sent with every product. They must match, or Merchant
Center rejects the products. Changing them later does not update an existing data
source: create a new one instead.
Credentials
The service account in GOOGLE_API_CREDENTIALS_PATH needs the
https://www.googleapis.com/auth/content scope and access to the Merchant Center
account in GOOGLE_MERCHANT_ID.
GOOGLE_MERCHANT_TRANSPORT is rest by default. Use grpc only where the PHP grpc
extension is installed.
Data sources API
use DescomMarket\Feeds\Google\Merchant\Services\DataSources\DataSourceService; DataSourceService::list(); // every data source of the account DataSourceService::resolve(); // the one products are sent to, created if missing DataSourceService::create('My feed name'); // a new primary product data source
use DescomMarket\Feeds\Google\Merchant\Services\DeveloperRegistration\DeveloperRegistrationService; DeveloperRegistrationService::gcpIds(); // registered projects, empty if none DeveloperRegistrationService::registerGcp($email); // what the command does
Google Indexer Url in Search Console
Automatically index your products in Google Search Console if dispatch event:
DescomMarket\Common\Events\Catalog\Products\ProductPublished
You can use this API to index your products in Google Search Console
use DescomMarket\Feeds\Google\Index\Services\EnqueueUrlService; EnqueueUrlService::publish($url); EnqueueUrlService::unpublish($url);
Or use events:
use DescomMarket\Common\Events\Urls\UrlCreated; use DescomMarket\Common\Events\Urls\UrlDeleted;