{ "info": { "author": "", "author_email": "Daniel Rodriguez ", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Programming Language :: Python", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy" ], "description": "# Google Ads API CLI and Prompt\n\n

\n \n \n \n \n \n \n \n \n \n \n \n \n \n

\n\nGoogle Ads Interface for humans.\n\n_This is a work in progress, please open an issue if you find any bugs or have any suggestions._\n\nFeatures:\n\n- A command line tool for executing GAQL queries against the Google Ads API.\n Like [psql](https://www.postgresql.org/docs/current/app-psql.html) for the Google Ads API.\n- A command line tool for managing Google Ads resources.\n Like [kubectl](https://kubernetes.io/docs/reference/kubectl/) for the Google Ads API.\n- Centralized configuration with multiple account management\n- Automatically update refresh token\n- Python API with Pandas integration\n\n## Installation\n\n```shell\npip install adsctl\n```\n\n## Getting started\n\nRequirements:\n\n- All the requirements to use the Google Ads API including a Developer Token and OAuth2 credentials\n- See [Google Ads API Quickstart](https://developers.google.com/google-ads/api/docs/first-call/overview) for more details.\n\n### Configuration\n\nThis project manages it's own configuration files.\nTo create the configuration file run:\n\n```shell\nadsctl config\n\n# Open the location of the config files\nadsctl config explore\n```\n\nOpen the new default config file and fill it with your credentials:\nDev Token, Client ID, Client Secret and Customer ID.\n\nTo login and get a refresh token:\n\n```shell\nadsctl auth \n```\n\nThe token is saved automatically in the config file.\nYou can see it by running:\n\n```shell\n# View config\nadsctl config view\n```\n\n### Multiple Accounts\n\nYou can manage multiple accounts in the config file by adding TOML sections.\n\n```toml\ncurrent_account = \"default\"\n\n[... default account ...]\n\n[accounts.another]\ndeveloper_token = \"\"\ncustomer_id = \"\"\nlogin_customer_id = \"\"\n\n[accounts.another.oauth]\nclient_id = \"\"\nclient_secret = \"\"\n```\n\nSet the current account:\n\n```shell\n$ adsctl config set-account another\n$ adsctl config get-account\nanother\n```\n\n## GAQL Prompt\n\nAn interactive shell for executing GAQL queries against the Google Ads API.\n\n```shell\n$ gaql\n\n>>> SELECT campaign.id, campaign.name FROM campaign ORDER BY campaign.id\n+----+-----------------------------+---------+-------------+\n| | resourceName | name | id |\n|----+-----------------------------+---------+-------------|\n| 0 | customers/XXX/campaigns/YYY | name1 | 10000000000 |\n| 1 | customers/XXX/campaigns/YYY | name2 | 10000000000 |\n| 2 | customers/XXX/campaigns/YYY | name3 | 10000000000 |\n+----+-----------------------------+---------+-------------+\n```\n\nBy default it uses the it in `table` format but you can control the output\nformat with the `-o` option:\n\n```shell\n# Print the plain protobuf response\n$ gaql -o plain\n\n# Print the contents of a CSV file\n$ gaql -o csv\n```\n\nYou can also run a single inline command and redirect the output to a file:\n\n```shell\ngaql -c 'SELECT campaign.id, campaign.name FROM campaign ORDER BY campaign.id' -o csv > my-query.csv\n```\n\nThis assumes only table is returned but in more complex queries that include other\nresources or when using metrics or segments multiple tables are created.\nOn those cases use the -o csv-files flag to save each table to a different file\nbased on the table name.\n\n```shell\n$ gaql -c 'SELECT campaign.id, campaign.name FROM campaign ORDER BY campaign.id' -o csv-files\n\n$ ls\ncampaign.csv\n```\n\n### Query variables\n\nYou can specify one or more variables using the jinja syntax, those\nvariables will be replaced with the values specified in the `-v` options.\n\n```shell\ngaql -c 'SELECT campaign.id, campaign.name FROM campaign WHERE campaign.id = {{ id }} ORDER BY campaign.id' -v id=123456789\n```\n\nYou can also pass `-v` without a command and use this the variables in the prompt\nqueries:\n\n```shell\n$ gaql -v id=123456789 -v field=name\n\n>>> SELECT campaign.id, campaign.{{ field }} FROM campaign WHERE campaign.id = {{ id }} ORDER BY campaign.id\n```\n\n### Other options\n\nYou can overwrite the account and customer ID using the `-a` and `-i` options.\nSee `gaql --help` for more details.\n\n## CLI\n\n### Campaign Management\n\n#### Get campaigns\n\n````shell\n\n```shell\nadsctl get campaign\n````\n\n```plain\nName Status Id\n-------------------------------------------- -------- -----------\nInterplanetary Cruise Campaign #168961427368 Paused 20370195066\nInterplanetary Cruise Campaign #168961215970 Paused 20379497161\n```\n\n#### Status Management\n\n```shell\nadsctl edit campaign -i status enabled\n\nadsctl edit campaign -i 20370195066 status enabled\n```\n\n```shell\nadsctl get campaign\n```\n\n```plain\nName Status Id\n-------------------------------------------- -------- -----------\nInterplanetary Cruise Campaign #168961427368 Enabled 20370195066\nInterplanetary Cruise Campaign #168961215970 Paused 20379497161\n```\n\n#### Update budget\n\n```shell\nadsctl edit campaign -i budget \n```\n\n## Python API\n\nYou can also use the Python API to easily execute GAQL queries\nand get the results as a Python dict or pandas DataFrame.\n\n```python\nimport adsctl as ads\n\n# Read config file and creates the Google Ads client\ngoogle_ads = ads.GoogleAds()\n\n# Execute GAQL query\nget_campaigns_query = \"\"\"\nSELECT campaign.name,\n campaign_budget.amount_micros,\n campaign.status,\n campaign.optimization_score,\n campaign.advertising_channel_type,\n metrics.clicks,\n metrics.impressions,\n metrics.ctr,\n metrics.average_cpc,\n metrics.cost_micros,\n campaign.bidding_strategy_type\nFROM campaign\nWHERE segments.date DURING LAST_7_DAYS\n AND campaign.status != '{{ status }}'\n\"\"\"\n\ntables = google_ads.query(get_campaigns_query, params={\"status\": \"REMOVED\"}})\n\n# Print Pandas DataFrames\nfor table_name, table in tables.items():\n print(table_name)\n print(table, \"\\n\")\n```\n\n```plain\ncampaign\n resourceName status ... name optimizationScore\n0 customers/XXXXXXXXXX/campaigns/YYYYYYYYYYY ENABLED ... my-campaign 0.839904\n[1 rows x 6 columns]\n\nmetrics\n clicks costMicros ctr averageCpc impressions\n0 210 6730050 0.011457 32047.857143 18330\n\ncampaignBudget\n resourceName amountMicros\n0 customers/XXXXXXXXXX/campaignBudgets/ZZZZZZZZZZZ 1000000\n```\n\n## Disclaimer\n\n_This is not an official Google product_.\n\nThis repository is maintained by a Googler but is not a supported Google product.\nCode and issues here are answered by maintainers and other community members on GitHub on a best-effort basis.\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "", "keywords": "cli,google ads,google ads api,prompt", "license": "", "maintainer": "", "maintainer_email": "", "name": "adsctl", "package_url": "https://pypi.org/project/adsctl/", "platform": null, "project_url": "https://pypi.org/project/adsctl/", "project_urls": { "Documentation": "https://github.com/danielfrg/adsctl#readme", "Issues": "https://github.com/danielfrg/adsctl/issues", "Source": "https://github.com/danielfrg/adsctl" }, "release_url": "https://pypi.org/project/adsctl/0.4.1/", "requires_dist": [ "click>=8.1", "google-ads>=20.0.0", "jinja2>=3.1.0", "pandas>=2.0.0", "pillow>=9.5.0", "prompt-toolkit>=3.0.38", "pydantic<2.0.0,>=1.10.0", "tabulate>=0.9.0", "tomli-w>=1.0", "tomlkit>=0.11.1", "coverage[toml]; extra == 'test'", "pytest; extra == 'test'", "pytest-cov; extra == 'test'" ], "requires_python": ">=3.8", "summary": "Google Ads Control CLI and Prompt", "version": "0.4.1", "yanked": false, "yanked_reason": null }, "last_serial": 19029693, "releases": { "0.1.0": [ { "comment_text": null, "digests": { "blake2b_256": "8089fce5a0ac3777ef43111c7870a1e1b6f4bfdaed3acf94f19f120f117c6d82", "md5": "565a3b792524bd344b20475b118bf757", "sha256": "3be125d2e9729984ed261d2816ef26c783e0ee1e664409e3d628fd7e7797905f" }, "downloads": -1, "filename": "adsctl-0.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "565a3b792524bd344b20475b118bf757", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.8", "size": 13117, "upload_time": "2023-03-14T03:42:42", "upload_time_iso_8601": "2023-03-14T03:42:42.972584Z", "url": "https://files.pythonhosted.org/packages/80/89/fce5a0ac3777ef43111c7870a1e1b6f4bfdaed3acf94f19f120f117c6d82/adsctl-0.1.0-py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": null, "digests": { "blake2b_256": "6e1c989d72993ae532f40eb80a2e0fbbb80d375092f97c43d174b72e4b05053f", "md5": "fe493d565e706d758bce8f4371c30343", "sha256": "7ebd346dba6d99c4d92263d78b298cef58a6562a5d594f0d55f02ad33688be30" }, "downloads": -1, "filename": "adsctl-0.1.0.tar.gz", "has_sig": false, "md5_digest": "fe493d565e706d758bce8f4371c30343", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.8", "size": 11529, "upload_time": "2023-03-14T03:42:45", "upload_time_iso_8601": "2023-03-14T03:42:45.225985Z", "url": "https://files.pythonhosted.org/packages/6e/1c/989d72993ae532f40eb80a2e0fbbb80d375092f97c43d174b72e4b05053f/adsctl-0.1.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.2.0": [ { "comment_text": null, "digests": { "blake2b_256": "512ee263e74bf061cd55ee1736d9c9f8d9e56427314f94d12f75c0721f836fc3", "md5": "b421e13a4dca237f91a03ee18f5019da", "sha256": "a31b74a98fc47b5beb13e53f2cf1e6d73ceef41159c3e49a392b2d66aeea8342" }, "downloads": -1, "filename": "adsctl-0.2.0-py3-none-any.whl", "has_sig": false, "md5_digest": "b421e13a4dca237f91a03ee18f5019da", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.10", "size": 22207, "upload_time": "2023-04-19T20:40:41", "upload_time_iso_8601": "2023-04-19T20:40:41.514352Z", "url": "https://files.pythonhosted.org/packages/51/2e/e263e74bf061cd55ee1736d9c9f8d9e56427314f94d12f75c0721f836fc3/adsctl-0.2.0-py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": null, "digests": { "blake2b_256": "8373d8fdb0e95fe9b0e4ab2b84581a34b418386368f4cfbb664fc9b7f5f0b107", "md5": "dc88eb00c04088ad410f400062d64257", "sha256": "20164a6ea6f0b57223d318b30c632d983f7bff3a727b63e62e8676449bfcc36f" }, "downloads": -1, "filename": "adsctl-0.2.0.tar.gz", "has_sig": false, "md5_digest": "dc88eb00c04088ad410f400062d64257", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.10", "size": 23604, "upload_time": "2023-04-19T20:40:43", "upload_time_iso_8601": "2023-04-19T20:40:43.986865Z", "url": "https://files.pythonhosted.org/packages/83/73/d8fdb0e95fe9b0e4ab2b84581a34b418386368f4cfbb664fc9b7f5f0b107/adsctl-0.2.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.3.0": [ { "comment_text": null, "digests": { "blake2b_256": "80ac08945f5d8d9912172a827e896cec5c4b95e8031a725c83ec3a5115649251", "md5": "bc3ffd8fb570ee14604b7753e93961d2", "sha256": "7022b8454915126578a349a39dfeea04a0c5d7e21d5e4cd372be9c6af61a0eec" }, "downloads": -1, "filename": "adsctl-0.3.0-py3-none-any.whl", "has_sig": false, "md5_digest": "bc3ffd8fb570ee14604b7753e93961d2", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.10", "size": 26161, "upload_time": "2023-04-26T16:08:30", "upload_time_iso_8601": "2023-04-26T16:08:30.772703Z", "url": "https://files.pythonhosted.org/packages/80/ac/08945f5d8d9912172a827e896cec5c4b95e8031a725c83ec3a5115649251/adsctl-0.3.0-py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": null, "digests": { "blake2b_256": "d75859224f03c97c2583bf1fcb1ef9e8a1053457375d106f730aba53b3a0f609", "md5": "9b2256b7d49abbb25d2b4d4fcffccb0e", "sha256": "b3871aa596b11463af273f51eb4ece7b96d136be5dd726d2c90b8bf00165281e" }, "downloads": -1, "filename": "adsctl-0.3.0.tar.gz", "has_sig": false, "md5_digest": "9b2256b7d49abbb25d2b4d4fcffccb0e", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.10", "size": 23672, "upload_time": "2023-04-26T16:08:33", "upload_time_iso_8601": "2023-04-26T16:08:33.053909Z", "url": "https://files.pythonhosted.org/packages/d7/58/59224f03c97c2583bf1fcb1ef9e8a1053457375d106f730aba53b3a0f609/adsctl-0.3.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.4.0": [ { "comment_text": "", "digests": { "blake2b_256": "c7ddf98f83017a9ff00d80b59e7b9dc6b7d1195a64c3acb1b5bc7c5b818557e0", "md5": "87d1c6968527d68d2c11e30d6806f015", "sha256": "4a51342a09c1227dd85f3a6b98de578f2572722136455074f72d05d2da6eb273" }, "downloads": -1, "filename": "adsctl-0.4.0-py3-none-any.whl", "has_sig": false, "md5_digest": "87d1c6968527d68d2c11e30d6806f015", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.8", "size": 27931, "upload_time": "2023-07-12T17:00:02", "upload_time_iso_8601": "2023-07-12T17:00:02.868433Z", "url": "https://files.pythonhosted.org/packages/c7/dd/f98f83017a9ff00d80b59e7b9dc6b7d1195a64c3acb1b5bc7c5b818557e0/adsctl-0.4.0-py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "blake2b_256": "ef59c19f7b9f4d29f2266ac1d31e55f9601c67b0d0eb2fd2af4bf7e9c60d8f05", "md5": "2cc0c5f679b3a4563fb80a5d0dd77f3a", "sha256": "9fad7f84f08c278e898c9d9cd559fcc55aaad5f20ce60bee3729d792561ad0e3" }, "downloads": -1, "filename": "adsctl-0.4.0.tar.gz", "has_sig": false, "md5_digest": "2cc0c5f679b3a4563fb80a5d0dd77f3a", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.8", "size": 24437, "upload_time": "2023-07-12T17:00:05", "upload_time_iso_8601": "2023-07-12T17:00:05.333942Z", "url": "https://files.pythonhosted.org/packages/ef/59/c19f7b9f4d29f2266ac1d31e55f9601c67b0d0eb2fd2af4bf7e9c60d8f05/adsctl-0.4.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.4.1": [ { "comment_text": "", "digests": { "blake2b_256": "52e18542c38ea922d008b08949d7501f9803c1b91c8ba147b5994c244cdf8b9c", "md5": "6f7510b52a03c9a43645ac3209d9fa3f", "sha256": "c95fc03c3fb986bd7bcf3fa8de676d3d98faabee6073790c6047078e30af8f74" }, "downloads": -1, "filename": "adsctl-0.4.1-py3-none-any.whl", "has_sig": false, "md5_digest": "6f7510b52a03c9a43645ac3209d9fa3f", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.8", "size": 28950, "upload_time": "2023-07-25T13:47:31", "upload_time_iso_8601": "2023-07-25T13:47:31.178171Z", "url": "https://files.pythonhosted.org/packages/52/e1/8542c38ea922d008b08949d7501f9803c1b91c8ba147b5994c244cdf8b9c/adsctl-0.4.1-py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "blake2b_256": "d6274c2a012014a868a19951bffd60bc82ca2e06cdff18aa90c56eaf138637e2", "md5": "617d57d128690c1b6c7b84488760201a", "sha256": "b753ebc9620887ce7cda000e02c19d4163317aab778e8390652683079c19dbd9" }, "downloads": -1, "filename": "adsctl-0.4.1.tar.gz", "has_sig": false, "md5_digest": "617d57d128690c1b6c7b84488760201a", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.8", "size": 24936, "upload_time": "2023-07-25T13:47:32", "upload_time_iso_8601": "2023-07-25T13:47:32.491614Z", "url": "https://files.pythonhosted.org/packages/d6/27/4c2a012014a868a19951bffd60bc82ca2e06cdff18aa90c56eaf138637e2/adsctl-0.4.1.tar.gz", "yanked": false, "yanked_reason": null } ] }, "urls": [ { "comment_text": "", "digests": { "blake2b_256": "52e18542c38ea922d008b08949d7501f9803c1b91c8ba147b5994c244cdf8b9c", "md5": "6f7510b52a03c9a43645ac3209d9fa3f", "sha256": "c95fc03c3fb986bd7bcf3fa8de676d3d98faabee6073790c6047078e30af8f74" }, "downloads": -1, "filename": "adsctl-0.4.1-py3-none-any.whl", "has_sig": false, "md5_digest": "6f7510b52a03c9a43645ac3209d9fa3f", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.8", "size": 28950, "upload_time": "2023-07-25T13:47:31", "upload_time_iso_8601": "2023-07-25T13:47:31.178171Z", "url": "https://files.pythonhosted.org/packages/52/e1/8542c38ea922d008b08949d7501f9803c1b91c8ba147b5994c244cdf8b9c/adsctl-0.4.1-py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "blake2b_256": "d6274c2a012014a868a19951bffd60bc82ca2e06cdff18aa90c56eaf138637e2", "md5": "617d57d128690c1b6c7b84488760201a", "sha256": "b753ebc9620887ce7cda000e02c19d4163317aab778e8390652683079c19dbd9" }, "downloads": -1, "filename": "adsctl-0.4.1.tar.gz", "has_sig": false, "md5_digest": "617d57d128690c1b6c7b84488760201a", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.8", "size": 24936, "upload_time": "2023-07-25T13:47:32", "upload_time_iso_8601": "2023-07-25T13:47:32.491614Z", "url": "https://files.pythonhosted.org/packages/d6/27/4c2a012014a868a19951bffd60bc82ca2e06cdff18aa90c56eaf138637e2/adsctl-0.4.1.tar.gz", "yanked": false, "yanked_reason": null } ], "vulnerabilities": [] }