Skip to content

Commit e1c51b4

Browse files
authored
Merge pull request #57 from google-marketing-solutions/release-v1.3
Release v1.3
2 parents 489261c + 3fd2dff commit e1c51b4

7 files changed

Lines changed: 348 additions & 37 deletions

File tree

CODE_OF_CONDUCT.md

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<!--
2+
Copyright 2023 Google LLC
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
16+
# Code of Conduct
17+
18+
## Our Pledge
19+
20+
In the interest of fostering an open and welcoming environment, we as
21+
contributors and maintainers pledge to making participation in our project and
22+
our community a harassment-free experience for everyone, regardless of age, body
23+
size, disability, ethnicity, gender identity and expression, level of
24+
experience, education, socio-economic status, nationality, personal appearance,
25+
race, religion, or sexual identity and orientation.
26+
27+
## Our Standards
28+
29+
Examples of behavior that contributes to creating a positive environment
30+
include:
31+
32+
- Using welcoming and inclusive language
33+
- Being respectful of differing viewpoints and experiences
34+
- Gracefully accepting constructive criticism
35+
- Focusing on what is best for the community
36+
- Showing empathy towards other community members
37+
38+
Examples of unacceptable behavior by participants include:
39+
40+
- The use of sexualized language or imagery and unwelcome sexual attention or
41+
advances
42+
- Trolling, insulting/derogatory comments, and personal or political attacks
43+
- Public or private harassment
44+
- Publishing others' private information, such as a physical or electronic
45+
address, without explicit permission
46+
- Other conduct which could reasonably be considered inappropriate in a
47+
professional setting
48+
49+
## Our Responsibilities
50+
51+
Project maintainers are responsible for clarifying the standards of acceptable
52+
behavior and are expected to take appropriate and fair corrective action in
53+
response to any instances of unacceptable behavior.
54+
55+
Project maintainers have the right and responsibility to remove, edit, or reject
56+
comments, commits, code, wiki edits, issues, and other contributions that are
57+
not aligned to this Code of Conduct, or to ban temporarily or permanently any
58+
contributor for other behaviors that they deem inappropriate, threatening,
59+
offensive, or harmful.
60+
61+
## Scope
62+
63+
This Code of Conduct applies both within project spaces and in public spaces
64+
when an individual is representing the project or its community. Examples of
65+
representing a project or community include using an official project e-mail
66+
address, posting via an official social media account, or acting as an appointed
67+
representative at an online or offline event. Representation of a project may be
68+
further defined and clarified by project maintainers.
69+
70+
This Code of Conduct also applies outside the project spaces when the Project
71+
Steward has a reasonable belief that an individual's behavior may have a
72+
negative impact on the project or its community.
73+
74+
## Conflict Resolution
75+
76+
We do not believe that all conflict is bad; healthy debate and disagreement
77+
often yield positive results. However, it is never okay to be disrespectful or
78+
to engage in behavior that violates the project’s code of conduct.
79+
80+
If you see someone violating the code of conduct, you are encouraged to address
81+
the behavior directly with those involved. Many issues can be resolved quickly
82+
and easily, and this gives people more control over the outcome of their
83+
dispute. If you are unable to resolve the matter for any reason, or if the
84+
behavior is threatening or harassing, report it. We are dedicated to providing
85+
an environment where participants feel welcome and safe.
86+
87+
Reports should be directed to _[PROJECT STEWARD NAME(s) AND EMAIL(s)]_, the
88+
Project Steward(s) for _[PROJECT NAME]_. It is the Project Steward’s duty to
89+
receive and address reported violations of the code of conduct. They will then
90+
work with a committee consisting of representatives from the Open Source
91+
Programs Office and the Google Open Source Strategy team. If for any reason you
92+
are uncomfortable reaching out to the Project Steward, please email
93+
opensource@google.com.
94+
95+
We will investigate every complaint, but you may not receive a direct response.
96+
We will use our discretion in determining when and how to follow up on reported
97+
incidents, which may range from not taking action to permanent expulsion from
98+
the project and project-sponsored spaces. We will notify the accused of the
99+
report and provide them an opportunity to discuss it before any action is taken.
100+
The identity of the reporter will be omitted from the details of the report
101+
supplied to the accused. In potentially harmful situations, such as ongoing
102+
harassment or threats to anyone's safety, we may take action without notice.
103+
104+
## Attribution
105+
106+
This Code of Conduct is adapted from the Contributor Covenant, version 1.4,
107+
available at
108+
https://www.contributor-covenant.org/version/1/4/code-of-conduct/

CONTRIBUTING renamed to CONTRIBUTING.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
<!--
2+
Copyright 2023 Google LLC
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
116
# How to Contribute
217

318
We would love to accept your patches and contributions to this project.

README.md

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,24 +54,38 @@ Here are some of Adios's powerful features:
5454
- **Seamless A/B testing**: Easily create Google Ads experiments to compare the performance of your new image assets against your existing setup, optimizing click-through rates and campaign success.
5555

5656
## Releases & features
57+
58+
### Adios v1.3
59+
60+
Features:
61+
62+
- Increased configuration flexibility in the 'Config' sheet. Now you can easily change AI models, GCP region, and other settings without editing the code.
63+
- Improved the stability and reliability of Gen API interactions. The tool now automatically retries failed requests, ensuring a smoother and more robust user experience.
64+
- Improved documentation in the Config sheet and on GitHub ([README](README.md)) to provide clearer guidance and support.
65+
5766
### Adios v1.2
5867

5968
Features:
69+
6070
- [Enhanced Triggers](#enhanced-triggers): Optimized how long-running services operate, addressing execution time limits for large-scale ad group processing. (See Google Apps Script [quotas for details](https://developers.google.com/apps-script/guides/services/quotas#current_limitations)).
6171
- [Google Ads API Mocks](#google-ads-api-mocks): Experiment with Adios features and functionality without needing a Google Ads account.
6272
- Text-to-Image prompt generation has been switched to Gemini 1.5 Flash.
6373
- The Google Ads API has been upgraded to version 17.
6474

6575
### Adios v1.1
76+
6677
https://github.com/google-marketing-solutions/adios/assets/3335483/9be71a1a-43da-49ba-b203-598e797f1d64
6778

6879
Features:
80+
6981
- Automatic, AI ([Gemini](https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/overview)) based image policy validation. Now you can write your brand, company, _you name it_ ads policies as a text and the generated image will be validated against those policies.
7082
- Ad Group names translations. Now you can translate your ad group names (or parts of them) e.g. into better text-to-image prompts.
7183
- Keyword based image generation. Previously you could generate images only based on the ad group names.
7284

7385
### Adios v1.0
86+
7487
Features:
88+
7589
- Generate image assets (ad group level) based on the ad group names
7690
- Image validation UI (validate manually generated images before uploading to Google Ads).
7791
- Upload generated assets to the Google Ads assets library.
@@ -84,7 +98,9 @@ Note: these features can be used separately, e.g. you can just upload images to
8498

8599
https://github.com/google-marketing-solutions/adios/assets/3335483/f22172d3-38f1-4fdb-b366-67a33700180e
86100

87-
1. Make a copy of the [template Spreadsheet: Adios v1.2](https://docs.google.com/spreadsheets/d/1DUNphGZIRL6mPDyrqgXErL-7p-gs0WmTqIjZl2ZXdSM/edit?usp=sharing) (in the main menu `File > Make a copy`). Earlier versions:
101+
1. Make a copy of the [template Spreadsheet: Adios v1.3](https://docs.google.com/spreadsheets/d/1e4OXlUaAYI1B0n7j5WOGEbzNsmAAFfkGg8rXZXejk3c/edit?usp=sharing) (in the main menu `File > Make a copy`). Earlier versions:
102+
103+
- [Adios v1.2](https://docs.google.com/spreadsheets/d/1DUNphGZIRL6mPDyrqgXErL-7p-gs0WmTqIjZl2ZXdSM/edit?usp=sharing)
88104
- [Adios v1.1](https://docs.google.com/spreadsheets/d/1A0UbhSiF1ox47WUbA4VZ4oh4WlwzbRbkuQHQshHNWiU/edit?usp=sharing&resourcekey=0-283C6nDIyps8TKhcgtxXeQ)
89105
- [Adios 1.0](https://docs.google.com/spreadsheets/d/1YnFCTif5ruLqs4qJIMcJmvejMEhvFHBzkBwfDp_oWRE/edit?resourcekey=0-mj_eJDv4XRwv2zwOJnYXug)
90106

@@ -105,8 +121,28 @@ https://github.com/google-marketing-solutions/adios/assets/3335483/f22172d3-38f1
105121

106122
1. Now you can run or schedule the Adios services using the Adios menu
107123

124+
## Configuration
125+
126+
Adios' configuration parameters are primarily located in the default "Config" sheet of the [template spreadsheet](#installation-guide). It is essential to complete the configuration before using Adios.
127+
128+
Mandatory fields:
129+
130+
- GCP Project Specific Parameters
131+
- GCP Project
132+
- GCS Bucket
133+
- Google Ads Specific Parameters (in case you use [Mocks](#google-ads-api-mocks), this is not required)
134+
- Google Ads API Key (aka "developer token")
135+
- Account ID, Manager Account ID, Campaign IDs
136+
137+
Other Parameters:
138+
139+
- **Preset Parameters**: Several parameters in the "Config" sheet come with preset values. You can modify these if needed based on your specific requirements.
140+
- **Optional Parameters**: Adios offers additional optional parameters to fine-tune its behavior.
141+
108142
## Assets generation
109-
Notes:
143+
144+
Notes:
145+
110146
- this step is not required if you already have the assets.
111147
- starting from Adios v1.1 you can generate assets based on ad group keywords (check this [video](https://github.com/google-marketing-solutions/adios/assets/3335483/9be71a1a-43da-49ba-b203-598e797f1d64)).
112148

@@ -116,8 +152,8 @@ https://github.com/google-marketing-solutions/adios/assets/3335483/72db55da-7ed1
116152

117153
Want to try out image generation without real ad groups? Simulate them easily with a spreadsheet:
118154

119-
- __Configure Adios__: In the "Config" sheet, add a variable named "Google Ads Mock Sheet". Choose a name for your mock sheet (e.g., "Mock") and set it as the value for this variable.
120-
- __Create Your Mock Data__: Create a new sheet with the name you chose (e.g., "Mock"). Make sure it has two columns:
155+
- **Configure Adios**: In the "Config" sheet, add a variable named "Google Ads Mock Sheet". Choose a name for your mock sheet (e.g., "Mock") and set it as the value for this variable.
156+
- **Create Your Mock Data**: Create a new sheet with the name you chose (e.g., "Mock"). Make sure it has two columns:
121157
- "Ad Group Name": Enter a name for each simulated ad group.
122158
- "Keywords": List the keywords associated with each ad group (comma separated).
123159

@@ -162,6 +198,7 @@ As a result you will be able to see newly created experiments in the
162198
while your experiment is running may make it harder to interpret your results.
163199

164200
## Using the Validation UI
201+
165202
Adios provides an optional UI for users to check the generated images and approve/reject them before uploading them to the Google Ads account.
166203

167204
https://github.com/google-marketing-solutions/adios/assets/3335483/d3b15133-6f9e-4057-8fd7-b4ac77aff954
@@ -170,7 +207,7 @@ You can use it as follows:
170207

171208
1. Ensure that there is a set `Validated DIR` in the configuration Spreadsheet (e.g. `VALIDATED`)
172209

173-
This is the name for the directory in the GCS bucket, where approved images will be saved. Disapproved images will be saved to the directory specified in `Disapproved DIR`.
210+
This is the name for the directory in the GCS bucket, where approved images will be saved. Disapproved images will be saved to the directory specified in `Disapproved DIR`.
174211

175212
1. In the Spreadsheet, open Extensions > Apps Script
176213

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "adios",
3-
"version": "1.1",
4-
"description": "",
3+
"version": "1.3",
4+
"description": "Adios: One-stop solution for Google Ads image assets management",
55
"main": "build/index.js",
66
"license": "Apache-2.0",
77
"keywords": [],

src/config.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ interface Config {
4040
'Text Prompt Suffix': string;
4141
'Prompt translations sheet': string;
4242
'Google Ads Mock Sheet': string;
43+
'GCP Region'?: string;
44+
'VertexAI Api Domain Part'?: string;
45+
'Gemini Model'?: string;
46+
'Image Generation Model'?: string;
4347
}
4448

4549
export const sheet =
@@ -71,6 +75,10 @@ const DEFAULT_CONFIG = {
7175
'Text Prompt Suffix': '',
7276
'Prompt translations sheet': '',
7377
'Google Ads Mock Sheet': '',
78+
'GCP Region': undefined,
79+
'VertexAI Api Domain Part': undefined,
80+
'Gemini Model': undefined,
81+
'Image Generation Model': undefined,
7482
};
7583

7684
export const ADIOS_MODES = {

src/image-generation-service.ts

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,12 @@ import { ADIOS_MODES, CONFIG } from './config';
1717
import { GcsApi } from './gcs-api';
1818
import { GoogleAdsApiFactory } from './google-ads-api-mock';
1919
import { Triggerable } from './triggerable';
20-
import { VertexAiApi } from './vertex-ai-api';
20+
import {
21+
GeminiApiCallError,
22+
ImageGenerationApiCallError,
23+
JsonParseError,
24+
VertexAiApi,
25+
} from './vertex-ai-api';
2126

2227
export class ImageGenerationService extends Triggerable {
2328
private readonly _gcsApi;
@@ -28,8 +33,11 @@ export class ImageGenerationService extends Triggerable {
2833
super();
2934
this._gcsApi = new GcsApi(CONFIG['GCS Bucket']);
3035
this._vertexAiApi = new VertexAiApi(
31-
'us-central1-aiplatform.googleapis.com',
32-
CONFIG['GCP Project']!
36+
CONFIG['GCP Project'],
37+
CONFIG['GCP Region'],
38+
CONFIG['VertexAI Api Domain Part'],
39+
CONFIG['Gemini Model'],
40+
CONFIG['Image Generation Model']
3341
);
3442
this._googleAdsApi = GoogleAdsApiFactory.createObject();
3543
}
@@ -95,7 +103,7 @@ export class ImageGenerationService extends Triggerable {
95103
// Process it in batches of max VISION_API_LIMIT images (as for now, 4)
96104
while (generatedImages < adGroupImgCount && numTries <= MAX_TRIES) {
97105
const imgCount = Math.min(
98-
this._vertexAiApi.VISION_API_LIMIT,
106+
this._vertexAiApi.IMAGE_GENERATION_API_LIMIT,
99107
adGroupImgCount - generatedImages
100108
);
101109

@@ -161,7 +169,21 @@ export class ImageGenerationService extends Triggerable {
161169
textPrompt += ' ' + CONFIG['Text Prompt Suffix'];
162170
}
163171
Logger.log('Prompt to generate Imagen Prompt: ' + textPrompt);
164-
imgPrompt = this._vertexAiApi.callGeminiApi(textPrompt);
172+
try {
173+
imgPrompt = this._vertexAiApi.callGeminiApi(textPrompt);
174+
} catch (e) {
175+
if (e instanceof JsonParseError) {
176+
Logger.log('Gemini output is not correct JSON, retrying');
177+
} else if (e instanceof GeminiApiCallError) {
178+
Logger.log('Gemini call error, retrying');
179+
} else {
180+
throw e; // Unknown error
181+
}
182+
183+
// retrying
184+
numTries++;
185+
continue;
186+
}
165187
}
166188

167189
if (CONFIG['Prompt translations sheet']) {
@@ -175,7 +197,23 @@ export class ImageGenerationService extends Triggerable {
175197
Logger.log(
176198
`Imagen Prompt for AdGroup ${adGroup.adGroup.name}: "${imgPrompt}"`
177199
);
178-
const images = this._vertexAiApi.callVisionApi(imgPrompt, imgCount);
200+
201+
let images: string[] = [];
202+
try {
203+
images = this._vertexAiApi.callImageGenerationApi(
204+
imgPrompt,
205+
imgCount
206+
);
207+
} catch (e) {
208+
if (e instanceof ImageGenerationApiCallError) {
209+
Logger.log(
210+
'Not able to generate images, this might be because of the blocked content (see the logs)...'
211+
);
212+
} else {
213+
throw e; // Unknown error
214+
}
215+
}
216+
179217
Logger.log(
180218
`Received ${images?.length || 0} images for ${adGroup.adGroup.name}(${
181219
adGroup.adGroup.id

0 commit comments

Comments
 (0)