Responsive Search Ads

Use ResponsiveSearchAd to promote products on the Google Network. This ad type will compete in auctions with ExpandedTextAd. The main features of responsive search ads are that they allow you to:

  1. Set three or more headlines and two or more descriptions that will automatically rotate into the ad to determine which work best.
  2. Pin any headlines and descriptions you want so that they always appear in the ad.
  3. Collect performance statistics on different combinations of headlines and descriptions so you can see which ones are working and which ones aren't. The system will automatically favor headline and description combinations which work well together.
  4. Display customized URLs (as in expanded text ads). Specify path1 and path2, which will be appended to the end of your landing page domain to determine the displayed URL.

Format

Responsive search ads are displayed with three headlines and two descriptions at serve time, plus a customizable URL based on the landing page domain and how you've set up the path1 and path2 fields on your ad.

Here's an example of what an ad like this might look like, based on the example shown later in the guide:

Headlines and descriptions are wrapped in a new type of entity called an Asset. Each field is represented by an AssetLink array, which contain the Asset and some other information about how and when the headlines and descriptions can be used. There is no need to create assets in advance, as sending a new asset as part of the mutate call to create a responsive search ad automatically creates the appropriate Asset as well.

You can only use TextAsset for responsive search ads. These text assets are deduplicated behind the scenes, so using the same string in two different ads will result in those two ads sharing that asset. Assets are reviewed individually for policy violations and performance, which allows greater flexibility if only some of the assets are disapproved or underperforming.

Responsive search ads also support the new concept of pinning. If you want finer control than simply allowing the system to mix and match headlines and descriptions, you can pin headlines and descriptions to specific positions. For example, if you want a specific headline to always show first, you can set that AssetLink to have a pinnedField of HEADLINE_1. Then, whenever that ad is served, that specific text will be in the first headline position and the other fields will be drawn from the pool of remaining assets. If more than one asset is pinned to a specific position, then that position will rotate text between all assets that are pinned to that position.

Example

Each client library comes with examples that show how to create and get a responsive search ad. As with other ads, ad creation is accomplished using the AdGroupAdService.mutate() method. A ResponsiveSearchAd requires at least three headlines, at least two descriptions, and at least one final URL.

Java

ResponsiveSearchAd responsiveSearchAd = new ResponsiveSearchAd();
List<AssetLink> headlines = new ArrayList<>();
AssetLink pinnedHeadline =
    createAssetLinkForText("Cruise to Mars #" + System.currentTimeMillis());
// Set a pinning to always choose this asset for HEADLINE_1. Pinning is optional; if no pinning
// is set, then headlines and descriptions will be rotated and the ones that perform best will
// be used more often.
pinnedHeadline.setPinnedField(ServedAssetFieldType.HEADLINE_1);
headlines.add(pinnedHeadline);
headlines.add(createAssetLinkForText("Best Space Cruise Line"));
headlines.add(createAssetLinkForText("Experience the Stars"));
responsiveSearchAd.setHeadlines(headlines.toArray(new AssetLink[0]));

List<AssetLink> descriptions = new ArrayList<>();
descriptions.add(createAssetLinkForText("Buy your tickets now"));
descriptions.add(createAssetLinkForText("Visit the Red Planet"));
responsiveSearchAd.setDescriptions(descriptions.toArray(new AssetLink[0]));

responsiveSearchAd.setFinalUrls(new String[] {"http://www.example.com/cruise"});
responsiveSearchAd.setPath1("all-inclusive");
responsiveSearchAd.setPath2("deals");

// Create ad group ad.
AdGroupAd responsiveSearchAdGroupAd = new AdGroupAd();
responsiveSearchAdGroupAd.setAdGroupId(adGroupId);
responsiveSearchAdGroupAd.setAd(responsiveSearchAd);

// Optional: set the status.
responsiveSearchAdGroupAd.setStatus(AdGroupAdStatus.PAUSED);

C#

// Create a responsive search ad.
ResponsiveSearchAd responsiveSearchAd = new ResponsiveSearchAd()
{
    finalUrls = new string[]
    {
        "http://www.example.com/cruise"
    },
    path1 = "all-inclusive",
    path2 = "deals",
    headlines = new AssetLink[]
    {
        new AssetLink()
        {
            asset = new TextAsset()
            {
                assetText =
                    "Cruise to Mars #" + ExampleUtilities.GetShortRandomString(),
            },
            // Set a pinning to always choose this asset for HEADLINE_1.
            // Pinning is optional; if no pinning is set, then headlines
            // and descriptions will be rotated and the ones that perform
            // best will be used more often.
            pinnedField = ServedAssetFieldType.HEADLINE_1
        },
        new AssetLink()
        {
            asset = new TextAsset()
            {
                assetText = "Best Space Cruise Line",
            }
        },
        new AssetLink()
        {
            asset = new TextAsset()
            {
                assetText = "Experience the Stars",
            }
        },
    },
    descriptions = new AssetLink[]
    {
        new AssetLink()
        {
            asset = new TextAsset()
            {
                assetText = "Buy your tickets now",
            }
        },
        new AssetLink()
        {
            asset = new TextAsset()
            {
                assetText = "Visit the Red Planet",
            }
        },
    }
};

// Create ad group ad.
AdGroupAd adGroupAd = new AdGroupAd()
{
    adGroupId = adGroupId,
    ad = responsiveSearchAd,

    // Optional: Set additional settings.
    status = AdGroupAdStatus.PAUSED
};

Python

responsive_search_ad = {
    'xsi_type': 'AdGroupAd',
    'adGroupId': ad_group_id,
    'ad': {
        'xsi_type': 'ResponsiveSearchAd',
        'finalUrls': ['http://www.example.com/cruise'],
        'path1': 'all-inclusive',
        'path2': 'deals',
        'headlines': [{
            'asset': {
                'xsi_type': 'TextAsset',
                'assetText': 'Cruise to Mars # ' + str(uuid.uuid4())[:8]
            },
            'pinnedField': 'HEADLINE_1'
        }, {
            'asset': {
                'xsi_type': 'TextAsset',
                'assetText': 'Best Space Cruise Line',
            }
        }, {
            'asset': {
                'xsi_type': 'TextAsset',
                'assetText': 'Experience the Stars'
            }
        }],
        'descriptions': [{
            'asset': {
                'xsi_type': 'TextAsset',
                'assetText': 'Buy your tickets now.'
            }
        }, {
            'asset': {
                'xsi_type': 'TextAsset',
                'assetText': 'Visit the Red Planet',
            }
        }],
    },
    # Optional fields.
    'status': 'PAUSED'
}

PHP

// Create a responsive search ad.
$responsiveSearchAd = new ResponsiveSearchAd();
$responsiveSearchAd->setFinalUrls(['http://www.example.com/cruise']);
$responsiveSearchAd->setPath1('all-inclusive');
$responsiveSearchAd->setPath2('deals');

// Create text assets for headlines.
$headline1 = new TextAsset();
$headline1->setAssetText('Cruise to Mars #' . uniqid());
$headline2 = new TextAsset();
$headline2->setAssetText('Best Space Cruise Line');
$headline3 = new TextAsset();
$headline3->setAssetText('Experience the Stars');
$responsiveSearchAd->setHeadlines(
    [
        // Set a pinning to always choose this asset for HEADLINE_1.
        // Pinning is optional; if no pinning is set, then headlines
        // and descriptions will be rotated and the ones that perform
        // best will be used more often.
        new AssetLink($headline1, ServedAssetFieldType::HEADLINE_1),
        new AssetLink($headline2),
        new AssetLink($headline3)
    ]
);

// Create text assets for descriptions.
$description1 = new TextAsset();
$description1->setAssetText('Buy your tickets now');
$description2 = new TextAsset();
$description2->setAssetText('Visit the Red Planet');
$responsiveSearchAd->setDescriptions(
    [new AssetLink($description1), new AssetLink($description2)]
);

// Create ad group ad.
$adGroupAd = new AdGroupAd();
$adGroupAd->setAdGroupId($adGroupId);
$adGroupAd->setAd($responsiveSearchAd);

Perl

my $responsive_search_ad =
    Google::Ads::AdWords::v201806::ResponsiveSearchAd->new({
    headlines    => [
        Google::Ads::AdWords::v201806::AssetLink->new({
            asset       => Google::Ads::AdWords::v201806::TextAsset->new({
                assetText => "Cruise to Mars #" . substr(uniqid(), 0, 8)
            }),
            pinnedField => "HEADLINE_1"
        }),
        Google::Ads::AdWords::v201806::AssetLink->new({
            asset => Google::Ads::AdWords::v201806::TextAsset->new({
                assetText => "Best Space Cruise Line"
            }),
        }),
        Google::Ads::AdWords::v201806::AssetLink->new({
            asset => Google::Ads::AdWords::v201806::TextAsset->new({
                assetText => "Experience the Stars"
            }),
        }) ],
    descriptions => [
        Google::Ads::AdWords::v201806::AssetLink->new({
            asset => Google::Ads::AdWords::v201806::TextAsset->new({
                assetText => "Buy your tickets now"
            }),
        }),
        Google::Ads::AdWords::v201806::AssetLink->new({
            asset => Google::Ads::AdWords::v201806::TextAsset->new({
                assetText => "Visit the Red Planet"
            })
        })
    ],
    finalUrls    => [ "http://www.example.com/cruise" ],
    path1        => "all-inclusive",
    path2        => "deals"
});

my $ad_group_ad = Google::Ads::AdWords::v201806::AdGroupAd->new({
    adGroupId => $ad_group_id,
    ad        => $responsive_search_ad,
    # Additional properties (non-required).
    status    => "PAUSED"
});

Ruby

responsive_search_ad = {
  :xsi_type => 'ResponsiveSearchAd',
  :headlines => [
    {
      :asset => {
        :xsi_type => 'TextAsset',
        :asset_text => 'Cruise to Mars #%d' % (Time.new.to_f * 1000).to_i
      },
      # Set a pinning to always choose this asset for HEADLINE_1. Pinning is
      # optional; if no pinning is set, then headlines and descriptions will
      # be rotated and the ones that perform best will be used more often.
      :pinned_field => 'HEADLINE_1'
    },
    {
      :asset => {
        :xsi_type => 'TextAsset',
        :asset_text => 'Best Space Cruise Line'
      }
    },
    {
      :asset => {
        :xsi_type => 'TextAsset',
        :asset_text => 'Experience the Stars'
      }
    }
  ],
  :descriptions => [
    {
      :asset => {
        :xsi_type => 'TextAsset',
        :asset_text => 'Buy your tickets now'
      }
    },
    {
      :asset => {
        :xsi_type => 'TextAsset',
        :asset_text => 'Visit the Red Planet'
      }
    }
  ],
  :final_urls => ['http://www.example.com/cruise'],
  :path1 => 'all-inclusive',
  :path2 => 'deals'
}

ad_group_ad = {
  :ad_group_id => ad_group_id,
  :ad => responsive_search_ad,
  # Additional properties (non-required).
  :status => 'PAUSED'
}

VB.NET

' Create a responsive search ad.
Dim responsiveSearchAd As New ResponsiveSearchAd()
responsiveSearchAd.finalUrls = New String() {"http://www.example.com/cruise"}
responsiveSearchAd.path1 = "all-inclusive"
responsiveSearchAd.path2 = "deals"

Dim textAsset1 As New TextAsset()
textAsset1.assetText = "Cruise to Mars #" + ExampleUtilities.GetShortRandomString()

Dim headline1 As New AssetLink()
headline1.asset = textAsset1
' Set a pinning to always choose this asset for HEADLINE_1.
' Pinning Is optional; if no pinning is set, then headlines
' and descriptions will be rotated and the ones that perform
' best will be used more often.
headline1.pinnedField = ServedAssetFieldType.HEADLINE_1

Dim textAsset2 As New TextAsset()
textAsset2.assetText = "Best Space Cruise Line"

Dim headline2 As New AssetLink()
headline2.asset = textAsset2

Dim textAsset3 As New TextAsset()
textAsset3.assetText = "Experience the Stars"

Dim headline3 As New AssetLink()
headline3.asset = textAsset3

responsiveSearchAd.headlines = New AssetLink() {headline1, headline2, headline3}

' Create ad group ad.
Dim adGroupAd As New AdGroupAd()
adGroupAd.adGroupId = adGroupId
adGroupAd.ad = responsiveSearchAd

' Optional: Set additional settings.
adGroupAd.status = AdGroupAdStatus.PAUSED

To retrieve the responsive search ads you've created, call AdGroupAdService.get() with a predicate filtering on AdType RESPONSIVE_SEARCH_AD.

Java

// Get the AdGroupAdService.
AdGroupAdServiceInterface adGroupAdService =
    adWordsServices.get(session, AdGroupAdServiceInterface.class);

int offset = 0;
boolean morePages = true;

// Create selector to get all of the ads for the ad group.
SelectorBuilder builder = new SelectorBuilder();
Selector selector =
    builder
        .fields(
            AdGroupAdField.Id,
            AdGroupAdField.Status,
            AdGroupAdField.ResponsiveSearchAdHeadlines,
            AdGroupAdField.ResponsiveSearchAdDescriptions)
        .orderAscBy(AdGroupAdField.Id)
        .offset(offset)
        .limit(PAGE_SIZE)
        .equals(AdGroupAdField.AdGroupId, adGroupId.toString())
        .in(AdGroupAdField.Status, "ENABLED", "PAUSED")
        .equals("AdType", AdType.RESPONSIVE_SEARCH_AD.getValue())
        .build();

C#

using (AdGroupAdService adGroupAdService =
    (AdGroupAdService) user.GetService(AdWordsService.v201806.AdGroupAdService))
{
    // Create a selector to select all ads for the specified ad group.
    Selector selector = new Selector()
    {
        fields = new string[]
        {
            ResponsiveSearchAd.Fields.Id,
            AdGroupAd.Fields.Status,
            ResponsiveSearchAd.Fields.ResponsiveSearchAdHeadlines,
            ResponsiveSearchAd.Fields.ResponsiveSearchAdDescriptions
        },
        ordering = new OrderBy[]
        {
            OrderBy.Asc(ResponsiveSearchAd.Fields.Id)
        },
        predicates = new Predicate[]
        {
            // Restrict the fetch to only the selected ad group id.
            Predicate.Equals(AdGroupAd.Fields.AdGroupId, adGroupId),

            // Retrieve only responsive search ads.
            Predicate.Equals("AdType", AdType.RESPONSIVE_SEARCH_AD.ToString()),
        },
        paging = Paging.Default
    };

    AdGroupAdPage page = new AdGroupAdPage();
    try
    {
        do
        {
            // Get the responsive search ads.
            page = adGroupAdService.get(selector);

            // Display the results.
            if (page != null && page.entries != null)
            {
                int i = selector.paging.startIndex;

                foreach (AdGroupAd adGroupAd in page.entries)
                {
                    ResponsiveSearchAd ad = (ResponsiveSearchAd) adGroupAd.ad;
                    Console.WriteLine(
                        $"{i + 1} New responsive search ad with ID {ad.id} and " +
                        $"status {adGroupAd.status} was found.");
                    Console.WriteLine("Headlines:");
                    foreach (AssetLink headline in ad.headlines)
                    {
                        TextAsset textAsset = headline.asset as TextAsset;
                        Console.WriteLine($"    {textAsset.assetText}");
                        if (headline.pinnedFieldSpecified)
                        {
                            Console.WriteLine(
                                $"      (pinned to {headline.pinnedField})");
                        }
                    }

                    Console.WriteLine("Descriptions:");
                    foreach (AssetLink description in ad.descriptions)
                    {
                        TextAsset textAsset = description.asset as TextAsset;
                        Console.WriteLine($"    {textAsset.assetText}");
                        if (description.pinnedFieldSpecified)
                        {
                            Console.WriteLine(
                                $"      (pinned to {description.pinnedField})");
                        }
                    }

                    i++;
                }
            }

            selector.paging.IncreaseOffset();
        } while (selector.paging.startIndex < page.totalNumEntries);

        Console.WriteLine("Number of responsive search ads found: {0}",
            page.totalNumEntries);
    }
    catch (Exception e)
    {
        throw new System.ApplicationException("Failed to get responsive search ads.",
            e);
    }
}

Python

# Initialize appropriate service.
ad_group_ad_service = client.GetService('AdGroupAdService', version='v201806')

# Construct selector and get all ads for a given ad group.
offset = 0
selector = {
    'fields': ['Id', 'Status', 'ResponsiveSearchAdHeadlines',
               'ResponsiveSearchAdDescriptions'],
    'predicates': [
        {
            'field': 'AdGroupId',
            'operator': 'EQUALS',
            'values': [ad_group_id]
        },
        {
            'field': 'AdType',
            'operator': 'EQUALS',
            'values': ['RESPONSIVE_SEARCH_AD']
        }
    ],
    'paging': {
        'startIndex': str(offset),
        'numberResults': str(PAGE_SIZE)
    },
    'ordering': [
        {
            'field': 'Id',
            'sortOrder': 'ASCENDING'
        }
    ]
}

PHP

$adGroupAdService =
    $adWordsServices->get($session, AdGroupAdService::class);

// Create a selector to select all ads for the specified ad group.
$selectedFields = [
    'Id',
    'Status',
    'ResponsiveSearchAdHeadlines',
    'ResponsiveSearchAdDescriptions'
];
$query = (new ServiceQueryBuilder())->select($selectedFields)
    ->where('AdGroupId')
    ->in([$adGroupId])
    ->where('AdType')
    ->in([AdType::RESPONSIVE_SEARCH_AD])
    ->where('Status')
    ->in([AdGroupAdStatus::ENABLED, AdGroupAdStatus::PAUSED])
    ->orderByAsc('Id')
    ->limit(0, self::PAGE_LIMIT)
    ->build();

Perl

# Get all the ads for this ad group.
my $ad_group_predicate = Google::Ads::AdWords::v201806::Predicate->new({
    field    => "AdGroupId",
    operator => "IN",
    values   => [ $ad_group_id ] });
my $status_predicate = Google::Ads::AdWords::v201806::Predicate->new({
    field    => "Status",
    operator => "IN",
    values   => [ "ENABLED", "PAUSED" ] });
my $ad_type_predicate = Google::Ads::AdWords::v201806::Predicate->new({
    field    => "AdType",
    operator => "EQUALS",
    values   => [ "RESPONSIVE_SEARCH_AD" ] });

# Create selector.
my $paging = Google::Ads::AdWords::v201806::Paging->new({
    startIndex    => 0,
    numberResults => PAGE_SIZE
});
my $selector = Google::Ads::AdWords::v201806::Selector->new({
    fields     =>
        [ "Id", "Status", "ResponsiveSearchAdHeadlines",
            "ResponsiveSearchAdDescriptions" ],
    predicates =>
        [ $ad_group_predicate, $status_predicate, $ad_type_predicate ],
    ordering   => [
        Google::Ads::AdWords::v201806::OrderBy->new({
            field     => "Id",
            sortOrder => "ASCENDING"
        })
    ],
    paging     => $paging
});

Ruby

ad_group_ad_srv = adwords.service(:AdGroupAdService, API_VERSION)

# Get all the ads for this ad group.
selector = {
  :fields => ['Id', 'Status', 'ResponsiveSearchAdHeadlines',
      'ResponsiveSearchAdDescriptions'],
  :ordering => [{:field => 'Id', :sort_order => 'ASCENDING'}],
  # By default, disabled ads aren't returned by the selector. To return them,
  # include the DISABLED status in a predicate.
  :predicates => [
    {
      :field => 'AdGroupId',
      :operator => 'IN',
      :values => [ad_group_id]
    },
    {
      :field => 'Status',
      :operator => 'IN',
      :values => ['ENABLED', 'PAUSED']
    },
    {
      :field => 'AdType',
      :operator => 'EQUALS',
      :values => ['RESPONSIVE_SEARCH_AD']
    }
  ],
  :paging => {
    :start_index => 0,
    :number_results => PAGE_SIZE
  }
}

VB.NET

Using service As AdGroupAdService = CType(user.GetService(
    AdWordsService.v201806.AdGroupAdService), AdGroupAdService)

  ' Create a selector.
  Dim selector As New Selector

  selector.fields = New String() {
      ResponsiveSearchAd.Fields.Id, AdGroupAd.Fields.Status,
      ResponsiveSearchAd.Fields.ResponsiveSearchAdHeadlines,
      ResponsiveSearchAd.Fields.ResponsiveSearchAdDescriptions
  }

  selector.ordering = New OrderBy() {OrderBy.Asc(ResponsiveSearchAd.Fields.Id)}

  selector.predicates = New Predicate() {
    Predicate.Equals(AdGroupAd.Fields.AdGroupId, adGroupId),
    Predicate.Equals("AdType", AdType.RESPONSIVE_SEARCH_AD.ToString())
  }

  ' Select the selector paging.
  selector.paging = Paging.Default

  Dim page As New AdGroupAdPage

  Try
    Do
      ' Get the responsive search ads.
      page = service.get(selector)

      ' Display the results.
      If ((Not page Is Nothing) AndAlso (Not page.entries Is Nothing)) Then
        Dim i As Integer = selector.paging.startIndex

        For Each adGroupAd As AdGroupAd In page.entries
          Dim ad As ResponsiveSearchAd = CType(adGroupAd.ad, ResponsiveSearchAd)
          Console.WriteLine("{0} New responsive search ad with ID {1} and status " +
              "{2} was found.", i + 1, ad.id, adGroupAd.status)

          Console.WriteLine("Headlines:")

          For Each headline As AssetLink In ad.headlines
            Dim textAsset As TextAsset = CType(headline.asset, TextAsset)
            Console.WriteLine("    {0}", textAsset.assetText)
            If headline.pinnedFieldSpecified Then
              Console.WriteLine("      (pinned to {0})", headline.pinnedField)
            End If
          Next
          Console.WriteLine("Descriptions:")
          For Each description As AssetLink In ad.descriptions
            Dim textAsset As TextAsset = CType(description.asset, TextAsset)
            Console.WriteLine("    {0}", textAsset.assetText)
            If (description.pinnedFieldSpecified) Then
              Console.WriteLine("      (pinned to {0})", description.pinnedField)
            End If
          Next
        Next
        i += 1
      End If
      selector.paging.IncreaseOffset()
    Loop While (selector.paging.startIndex < page.totalNumEntries)
    Console.WriteLine("Number of responsive search ads found: {0}", page.totalNumEntries)
  Catch e As Exception
    Throw New System.ApplicationException("Failed to get responsive search ads.", e)
  End Try
End Using

Reporting

The AdType in reports for responsive search ads is RESPONSIVE_SEARCH_AD. The following fields in the Ad Performance report are specifically for responsive search ads:

  • ResponsiveSearchAdHeadlines
  • ResponsiveSearchAdDescriptions
  • ResponsiveSearchAdPath1
  • ResponsiveSearchAdPath2

The ResponsiveSearchAdHeadlines and ResponsiveSearchAdDescription fields each return a JSON object that can be parsed to determine the pinning, text, and performance all in a single field.

For example, the ResponsiveSearchAdHeadlines field for the responsive search ad created by the example above would look like this:

[
  {
    "assetText":"Cruise to Mars #1234",
    "assetId":1234,
    "pinnedField":"HEADLINE_1",
    "assetPerformanceLabel":"PENDING",
    "assetApprovalStatus":"UNDER_REVIEW"
  },
  {
    "assetText":"Best Space Cruise Line",
    "assetId":5678,
    "assetPerformanceLabel":"PENDING",
    "assetApprovalStatus":"UNDER_REVIEW"
  },
  {
    "assetText":"Experience the Stars",
    "assetId":9010,
    "assetPerformanceLabel":"PENDING",
    "assetApprovalStatus":"UNDER_REVIEW"
  }
]

Send feedback about...

AdWords API
AdWords API
Need help? Visit our support page.