نقل البيانات من Content API for Shopping إلى Merchant API

يشرح هذا الدليل عملية نقل البيانات من Content API for Shopping إلى Merchant API لإدارة بيانات النشاط الإعلاني.

يمكنك استخدام هذا الدليل لنقل بيانات عملية التنفيذ الحالية في Content API for Shopping إلى Merchant API. لمزيد من المعلومات حول تفاصيل Merchant API وواجهات برمجة التطبيقات الفرعية، يُرجى الاطّلاع على تصميم Merchant API.

البدء

لبدء استخدام Merchant API، غيِّر عناوين URL للطلبات إلى التنسيق التالي:

https://merchantapi.googleapis.com/{SUB_API}/{VERSION}/{RESOURCE_NAME}:{METHOD}

لاستخدام Merchant API، يجب ربط حسابك على Merchant Center بمشروعك على Google Cloud باستخدام طريقة تسجيل المطوّر، على النحو التالي:

POST https://merchantapi.googleapis.com/accounts/v1/accounts/{ACCOUNT_ID}/developerRegistration:registerGcp

{
  developer_email:"example-email@example.com"
}

لمزيد من المعلومات، يُرجى الاطّلاع على دليل البدء السريع ومرجع Merchant API.

التحسينات مقارنةً بـ Content API for Shopping

تتيح لك Merchant API أتمتة وتبسيط سير العمل في Merchant Center وتوفّر إمكانات محسّنة مقارنةً بـ Content API for Shopping.

أبرز حالات الاستخدام:

  • الإدارة التلقائية للحساب
  • الإدارة التلقائية للمنتجات
  • نظام إدارة المخزون التلقائي
  • إعداد التقارير المخصّصة

أبرز مجالات التحسين:

التغييرات التي تم إجراؤها:

  • تمت زيادة الحدّ الأقصى لـ pageSize من 250 إلى 1000 صف لكل طلب بيانات من واجهة برمجة التطبيقات.
  • تم حلّ مشكلة التأخير التي كانت تحدث عند إدراج المنتجات والعروض الترويجية ومراجعات المنتجات و مراجعات التجّار بعد DataSources الإنشاء تم حلّها.
  • تم إطلاق تعريف معدَّل لـ clickPotentialRank في جدول productView ضمن واجهة برمجة التطبيقات الفرعية إعداد التقارير:
    • يتمّ ضبط ترتيب المنتجات استنادًا إلى clickPotential على قيم تتراوح بين 1 و1000.
  • يتيح AccountIdAlias في مرجع AccountRelationship إدارة هياكل الحسابات المعقّدة بشكل أفضل. على سبيل المثال، تستخدم الأسواق اسمًا مستعارًا يحدّده المستخدم بدلاً من المعرّف الداخلي للتاجر، مثل رقم تعريف الحساب.

توافق gRPC

تتوافق Merchant API مع gRPC وREST. يمكنك استخدام gRPC لـ Merchant API وREST لـ Content API for Shopping في الوقت نفسه.

تتطلّب مكتبات عملاء Merchant API استخدام gRPC.

لمزيد من المعلومات، يُرجى الاطّلاع على نظرة عامة على gRPC.

التوافق

يصف هذا الدليل التغييرات العامة التي تنطبق على Merchant API بالكامل.

تم تصميم Merchant API للعمل جنبًا إلى جنب مع الميزات الحالية في Content API for Shopping.

على سبيل المثال، يمكنك استخدام Merchant Inventories API جنبًا إلى جنب مع عملية التنفيذ الحالية لـ Content API for Shopping الإصدار 2.1 products. يمكنك استخدام Content API for Shopping لتحميل منتج محلي جديد (تبيعه في متجر محلي)، ثم استخدام مرجع `LocalInventory` في Merchant Inventories API لإدارة معلومات هذا المنتج داخل المتجر.LocalInventory

التحسينات مقارنةً بـ Content API

تتفوّق Merchant API على Content API في المجالات التالية:

لنناقش هذه التغييرات بمزيد من التفصيل.

تحديد الإصدارات وواجهات برمجة التطبيقات الفرعية

تطرح Merchant API مفهومَي تحديد الإصدارات و واجهات برمجة التطبيقات الفرعية. يُسهّل تصميمها المعياري عملية الاستخدام، ما يسمح لك بالتركيز على واجهات برمجة التطبيقات الفرعية التي تحتاج إليها ويسهّل عمليات النقل المستقبلية إلى الإصدارات الأحدث. سيتم تطبيق تحديد الإصدارات على عناوين URL للطلبات. وتتشابه الاستراتيجية مع تجربة Google Ads API.

طلبات أكثر فعالية

تتطلّب طلبات عناوين URL في Merchant API المزيد من المَعلمات لاستدعاء Merchant API. ويشمل ذلك المرجع والإصدار والاسم (المعرّفات) والطريقة (الطُرق غير العادية). لمزيد من المعلومات حول هذا الموضوع، يُرجى الاطّلاع على معرّفات الحسابات والمنتجات و الأمثلة.

مبادئ AIP للمعرّفات

بينما تستخدم Content API for Shopping أرقام تعريف لتحديد المراجع (مثل merchantId وproductId)، تستخدم Merchant API معرّف name للتوافق مع AIP (يُرجى الاطّلاع على مبادئ تحسين واجهة برمجة التطبيقات).

يتضمّن المعرّف {name} معرّف المرجع والمرجع الرئيسي (أو قد يتضمّن عدة مراجع رئيسية)، بحيث يكون {name} مساويًا لـ accounts/{account}/products/{product}

تعرض جميع طلبات القراءة والكتابة حقل name كمعرّف للمرجع.

يتضمّن {name} أيضًا معرّفات المجموعة accounts/ وproducts/.

تستخدم Merchant API {account} للإشارة إلى رقم تعريف Merchant Center و{product} للإشارة إلى معرّفات المنتجات.

name

على سبيل المثال، يمكنك تنفيذ طريقة getName() لاسترداد name من مرجع وتخزين الناتج كمتغيّر بدلاً من إنشاء name من أرقام تعريف التاجر والمراجع بنفسك.

في ما يلي مثال على كيفية استخدام حقل name في طلباتك:

   POST https://merchantapi.googleapis.com/inventories/v1/{PARENT}/regionalInventories:insert

يوضّح الجدول كيفية تغيير طلب products.get في Content API for Shopping:

Content API for Shopping Merchant API
GET https://shoppingcontent.googleapis.com/content/v2.1/{merchantId}/products/{productId} GET https://merchantapi.googleapis.com/products/v1/{name}

لمزيد من التفاصيل، يُرجى مراجعة التغييرات في المعرّفات.

كمثال آخر، سيبدو استرداد منتج بالمعرّف en~US~1234 من رقم تعريف Merchant Center 4321 باستخدام Merchant API على النحو التالي:

    GET
    https://merchantapi.googleapis.com/products/v1/accounts/4321/products/online~en~US~1234

حيث يكون {name} مساويًا لـ accounts/4321/products/en~US~1234. يتم عرض حقل الاسم الجديد هذا كمعرّف للمرجع لجميع طلبات القراءة والكتابة في Merchant API.

في Content API for Shopping، تشير النقطتان (:) إلى فاصل في اسم المنتج، بينما تؤدي علامة المدة (~) هذه الوظيفة في Merchant API. لا يحتوي معرّف Merchant API على جزء channel.

على سبيل المثال، رقم تعريف المنتج في Content API for Shopping:

channel:contentLanguage:feedLabel:offerId

يصبح في Merchant API على النحو التالي:

contentLanguage~feedLabel~offerId

الحقول الرئيسية للمراجع الفرعية

في Merchant API، تحتوي جميع المراجع الفرعية على حقل parent. يمكنك استخدام حقل parent لتحديد {name} للمرجع الذي تريد إدراج المرجع الفرعي فيه، بدلاً من تمرير المرجع الرئيسي بالكامل. يمكنك أيضًا استخدام حقل parent مع list

على سبيل المثال، لعرض المستودعات المحلية لمنتج معيّن، حدِّد ال منتج's name في ال parent حقل لطريقة ال list. في هذه الحالة، يكون product المحدّد هو parent لمراجع LocalInventory التي يتم عرضها.

    GET
    https://merchantapi.googleapis.com/inventories/v1/{parent}/localInventories

لاسترداد جميع المستودعات المحلية للمنتج en~US~1234' والحساب 4321 ، سيبدو الطلب على النحو التالي:

    GET
    https://merchantapi.googleapis.com/inventories/v1/accounts/4321/products/online~en~US~1234/localInventories</code>

المرجع الرئيسي هو accounts/{account}/products/{product}. يُرجى العِلم أنّه في هذه الحالة يحتوي localInventories على مرجعَين رئيسيَين مضمّنين في معرّف الاسم (accounts/ و products/)، لأنّ الحساب هو المرجع الرئيسي لمرجع المنتج.

القيم الثابتة الشائعة

يوفّر استخدام القيم الثابتة الشائعة مزيدًا من الاتساق.

يحدّد الحقل Destination.DestinationEnum المنصات التي سيتم عرض مراجعك عليها. DestinationEnum تسرد جميع القيم المتاحة للاستهداف حسب الوجهة وهي موحّدة على مستوى واجهات برمجة التطبيقات الفرعية، مثلاً لـ سمات العروض الترويجية.

يمثّل الحقل ReportingContext.ReportingContextEnum السياق الذي تنطبق عليه مشاكل حسابك ومنتجاتك. يُستخدَم هذا الحقل في طُرق إعداد التقارير (مثلاً لـ IssueSeverityPerReportingContext).

التوافق مع الإصدارات السابقة

عند بدء استخدام Merchant API، ستستمر عملية الدمج الحالية في Content API for Shopping في العمل بدون انقطاع. لمزيد من المعلومات، يُرجى الاطّلاع على التوافق.

بعد نقل بيانات واجهات برمجة التطبيقات الفرعية إلى Merchant API، ننصحك باستخدام Merchant API فقط لواجهات برمجة التطبيقات الفرعية التي تم نقل بياناتها.

مدى توفّر استدعاء الإجراء عن بُعد (gRPC)

gRPC هو الطريقة الجديدة المقترَحة للدمج مع Merchant API.

تشمل مزاياه ما يلي:

تصبح عملية تجميع الطلبات المخصّصة عملية تجميع طلبات مضمّنة

تكون عملية تجميع الطلبات أكثر كفاءة عند استخدام طلبات غير متزامنة. مزيد من المعلومات حول استخدام الطلبات المتوازية لتحقيق عملية تجميع الطلبات في Merchant API وكيفية إعادة تصميم التعليمات البرمجية للطلبات المتزامنة requests.

للمساعدة في تسريع عملية نقل البيانات، ننصحك باستخدام مكتبات العملاء.

لا تتوافق Merchant API مع الطريقة customBatch المميّزة في Content API for Shopping. بدلاً من ذلك، يُرجى الاطّلاع على إرسال طلبات متعددة في وقت واحد أو تنفيذ طلباتك بشكل غير متزامن.

تعرض عيّنة Java التالية كيفية إدراج بيانات المنتج:

   import com.google.api.core.ApiFuture;
import com.google.api.core.ApiFutureCallback;
import com.google.api.core.ApiFutures;
import com.google.api.gax.core.FixedCredentialsProvider;
import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.shopping.merchant.products.v1.Availability;
import com.google.shopping.merchant.products.v1.Condition;
import com.google.shopping.merchant.products.v1.InsertProductInputRequest;
import com.google.shopping.merchant.products.v1.ProductAttributes;
import com.google.shopping.merchant.products.v1.ProductInput;
import com.google.shopping.merchant.products.v1.ProductInputsServiceClient;
import com.google.shopping.merchant.products.v1.ProductInputsServiceSettings;
import com.google.shopping.merchant.products.v1.Shipping;
import com.google.shopping.type.Price;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import shopping.merchant.samples.utils.Authenticator;
import shopping.merchant.samples.utils.Config;

/** This class demonstrates how to insert a product input */
public class InsertProductInputAsyncSample {

  private static String getParent(String accountId) {
    return String.format("accounts/%s", accountId);
  }

  private static String generateRandomString() {
    String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    Random random = new Random();
    StringBuilder sb = new StringBuilder(8);
    for (int i = 0; i < 8; i++) {
      sb.append(characters.charAt(random.nextInt(characters.length())));
    }
    return sb.toString();
  }

  private static ProductInput createRandomProduct() {
    Price price = Price.newBuilder().setAmountMicros(33_450_000).setCurrencyCode("USD").build();

    Shipping shipping =
        Shipping.newBuilder().setPrice(price).setCountry("GB").setService("1st class post").build();

    Shipping shipping2 =
        Shipping.newBuilder().setPrice(price).setCountry("FR").setService("1st class post").build();

    ProductAttributes attributes =
        ProductAttributes.newBuilder()
            .setTitle("A Tale of Two Cities")
            .setDescription("A classic novel about the French Revolution")
            .setLink("https://exampleWebsite.com/tale-of-two-cities.html")
            .setImageLink("https://exampleWebsite.com/tale-of-two-cities.jpg")
            .setAvailability(Availability.IN_STOCK)
            .setCondition(Condition.NEW)
            .setGoogleProductCategory("Media > Books")
            .addGtins("9780007350896")
            .addShipping(shipping)
            .addShipping(shipping2)
            .build();

    return ProductInput.newBuilder()
        .setContentLanguage("en")
        .setFeedLabel("CH")
        .setOfferId(generateRandomString())
        .setProductAttributes(attributes)
        .build();
  }

  public static void asyncInsertProductInput(Config config, String dataSource) throws Exception {

    // Obtains OAuth token based on the user's configuration.
    GoogleCredentials credential = new Authenticator().authenticate();

    // Creates a channel provider. This provider manages a pool of gRPC channels
    // to enhance throughput for bulk operations. Each individual channel in the pool
    // can handle up to approximately 100 concurrent requests.
    //
    // Channel: A single connection pathway to the service.
    // Pool: A collection of multiple channels managed by this provider.
    //   Requests are distributed across the channels in the pool.
    //
    // We recommend estimating the number of concurrent requests you'll make, divide by 50 (50%
    // utilization of channel capacity), and set the pool size to that number.
    InstantiatingGrpcChannelProvider channelProvider =
        InstantiatingGrpcChannelProvider.newBuilder().setPoolSize(30).build();

    // Creates service settings using the credentials retrieved above.
    ProductInputsServiceSettings productInputsServiceSettings =
        ProductInputsServiceSettings.newBuilder()
            .setCredentialsProvider(FixedCredentialsProvider.create(credential))
            .setTransportChannelProvider(channelProvider)
            .build();

    // Creates parent to identify where to insert the product.
    String parent = getParent(config.getAccountId().toString());

    // Calls the API and catches and prints any network failures/errors.
    try (ProductInputsServiceClient productInputsServiceClient =
        ProductInputsServiceClient.create(productInputsServiceSettings)) {

      // Creates five insert product input requests with random product IDs.
      List<InsertProductInputRequest> requests = new ArrayList<>(5);
      for (int i = 0; i < 5; i++) {
        InsertProductInputRequest request =
            InsertProductInputRequest.newBuilder()
                .setParent(parent)
                // You can only insert products into datasource types of Input "API", and of Type
                // "Primary" or "Supplemental."
                // This field takes the `name` field of the datasource.
                .setDataSource(dataSource)
                // If this product is already owned by another datasource, when re-inserting, the
                // new datasource will take ownership of the product.
                .setProductInput(createRandomProduct())
                .build();

        requests.add(request);
      }

      System.out.println("Sending insert product input requests");
      List<ApiFuture<ProductInput>> futures =
          requests.stream()
              .map(
                  request ->
                      productInputsServiceClient.insertProductInputCallable().futureCall(request))
              .collect(Collectors.toList());

      // Creates callback to handle the responses when all are ready.
      ApiFuture<List<ProductInput>> responses = ApiFutures.allAsList(futures);
      ApiFutures.addCallback(
          responses,
          new ApiFutureCallback<List<ProductInput>>() {
            @Override
            public void onSuccess(List<ProductInput> results) {
              System.out.println("Inserted products below");
              System.out.println(results);
            }

            @Override
            public void onFailure(Throwable throwable) {
              System.out.println(throwable);
            }
          },
          MoreExecutors.directExecutor());

    } catch (Exception e) {
      System.out.println(e);
    }
  }

  public static void main(String[] args) throws Exception {
    Config config = Config.load();
    // Identifies the data source that will own the product input.
    String dataSource = "accounts/" + config.getAccountId() + "/dataSources/{datasourceId}";

    asyncInsertProductInput(config, dataSource);
  }
}

إذا كنت تستخدم customBatch في Content API وتحتاج إلى هذه الميزة في Merchant API، يُرجى إعلامنا بالسبب في ملاحظاتك.

الميزات الحصرية

لن تظهر الميزات المستقبلية إلا في Merchant API. (ستكون هناك بعض الاستثناءات، مثل مواصفات الخلاصة السنوية لعام 2025).

تشمل الميزات الحصرية في Merchant API ما يلي:

  • واجهة برمجة التطبيقات الخاصة بالتعليقات: استخدِم التعليقات لتنفيذ وإدارة تقييمات منتجاتك ومتجرك. لمزيد من المعلومات، يُرجى الاطّلاع على مراجعة البائع ومراجعة المنتج.
  • الإشعارات: يمكنك الاشتراك لتلقّي إشعارات فورية بشأن التغييرات التي تطرأ على بيانات منتجات الحساب.

السعر

في ما يلي التغييرات التي تم إجراؤها على Price في حزمة Merchant Common:

Content API for Shopping Merchant API
حقل المبلغ value:string amountMicros:int64
حقل العملة currency:string currencyCode:string

يتم الآن تسجيل مبلغ Price بالميكرو، حيث يعادل مليون ميكرو الوحدة العادية لعملتك.

في Content API for Shopping، كان Price عددًا عشريًا على شكل سلسلة.

تم تغيير اسم حقل المبلغ من value إلى amountMicros

تم تغيير اسم حقل العملة من currency إلى currencyCode. وسيظل التنسيق هو ISO 4217.

آخر الأخبار والإعلانات

لمعرفة آخر الأخبار الأكثر تفصيلاً، يُرجى الاطّلاع على ملاحظات الإصدار الخاصة بكل واجهة برمجة تطبيقات فرعية. لمعرفة آخر الأخبار المجمّعة المنتظمة حول Merchant API، يُرجى مراجعة آخر الأخبار.

لمعرفة المزيد من التفاصيل المحدّدة والاطّلاع على مزيد من المعلومات حول Merchant API، يُرجى الاطّلاع على نظرة عامة على موقع المطوّرين ودليل نقل البيانات العام لمزيد من التفاصيل.

يُرجى الاطّلاع على تصميم Merchant API لمعرفة تفاصيل حول Merchant API وواجهات برمجة التطبيقات الفرعية.