├── .gitignore ├── src ├── Base.php ├── Accounts │ ├── AccountConfig.php │ └── Account.php ├── Reports │ ├── ReportInterface.php │ ├── CustomReport.php │ ├── FinalUrlReport.php │ ├── SearchQueryPerformanceReport.php │ ├── AdPerformanceReport.php │ ├── AccountPerformanceReport.php │ ├── AdGroupPerformanceReport.php │ ├── CampaignPerformanceReport.php │ ├── KeywordsPerformanceReport.php │ ├── ReportConfig.php │ └── Report.php ├── EntityInterface.php ├── Keywords │ ├── KeywordBatchConfig.php │ ├── KeywordBatch.php │ ├── KeywordBase.php │ ├── Keyword.php │ └── KeywordConfig.php ├── AdGroups │ ├── AdGroupConfig.php │ └── AdGroup.php ├── AdWordsAuth │ └── AdWordsAuth.php ├── Entity.php ├── Config.php └── Campaigns │ ├── Campaign.php │ └── CampaignConfig.php ├── phpdoc.xml ├── composer.json ├── LICENSE.md ├── docs └── diagrams │ └── EasyAdwords_ClassDiagram.uml ├── README.md └── composer.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | /node_modules 3 | /.idea -------------------------------------------------------------------------------- /src/Base.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | Easy AdWords Auto-Documentation 4 | 5 | docs/generated 6 | 7 | 8 | docs/generated 9 | 10 | 11 | ./src 12 | 13 | -------------------------------------------------------------------------------- /src/Accounts/AccountConfig.php: -------------------------------------------------------------------------------- 1 | downloadRawReport(); 27 | 28 | return $this; 29 | } 30 | 31 | /** 32 | * Format the raw CSV report into a flat array. 33 | * @return $this 34 | */ 35 | public function format() { 36 | $this->formatRawReport(); 37 | 38 | return $this; 39 | } 40 | } -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 AdProLabs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /src/EntityInterface.php: -------------------------------------------------------------------------------- 1 | reportType); 22 | } 23 | 24 | /** 25 | * Download the raw CSV report from AdWords and store in the object. 26 | * @return $this 27 | */ 28 | public function download() { 29 | $this->downloadRawReport(); 30 | 31 | return $this; 32 | } 33 | 34 | /** 35 | * Format the raw CSV report into a flat array. 36 | * @return $this 37 | */ 38 | public function format() { 39 | $this->formatRawReport(); 40 | 41 | return $this; 42 | } 43 | } -------------------------------------------------------------------------------- /src/Reports/SearchQueryPerformanceReport.php: -------------------------------------------------------------------------------- 1 | reportType); 21 | } 22 | 23 | /** 24 | * Download the raw CSV report from AdWords and store in the object. 25 | * @return $this 26 | */ 27 | public function download() { 28 | $this->downloadRawReport(); 29 | 30 | return $this; 31 | } 32 | 33 | /** 34 | * Format the raw CSV report into a flat array. 35 | * @return $this 36 | */ 37 | public function format() { 38 | $this->formatRawReport(); 39 | 40 | return $this; 41 | } 42 | } -------------------------------------------------------------------------------- /src/Reports/AdPerformanceReport.php: -------------------------------------------------------------------------------- 1 | reportType); 22 | } 23 | 24 | /** 25 | * Download the raw CSV report from AdWords and store in the object. 26 | * @return $this 27 | */ 28 | public function download() { 29 | $this->downloadRawReport(); 30 | 31 | return $this; 32 | } 33 | 34 | /** 35 | * Format the raw CSV report into a flat array. 36 | * @return $this 37 | */ 38 | public function format() { 39 | $this->formatRawReport(); 40 | 41 | return $this; 42 | } 43 | } -------------------------------------------------------------------------------- /src/Reports/AccountPerformanceReport.php: -------------------------------------------------------------------------------- 1 | reportType); 22 | } 23 | 24 | /** 25 | * Download the raw CSV report from AdWords and store in the object. 26 | * @return $this 27 | */ 28 | public function download() { 29 | $this->downloadRawReport(); 30 | 31 | return $this; 32 | } 33 | 34 | /** 35 | * Format the raw CSV report into a flat array. 36 | * @return $this 37 | */ 38 | public function format() { 39 | $this->formatRawReport(); 40 | 41 | return $this; 42 | } 43 | } -------------------------------------------------------------------------------- /src/Reports/AdGroupPerformanceReport.php: -------------------------------------------------------------------------------- 1 | reportType); 22 | } 23 | 24 | /** 25 | * Download the raw CSV report from AdWords and store in the object. 26 | * @return $this 27 | */ 28 | public function download() { 29 | $this->downloadRawReport(); 30 | 31 | return $this; 32 | } 33 | 34 | /** 35 | * Format the raw CSV report into a flat array. 36 | * @return $this 37 | */ 38 | public function format() { 39 | $this->formatRawReport(); 40 | 41 | return $this; 42 | } 43 | } -------------------------------------------------------------------------------- /src/Reports/CampaignPerformanceReport.php: -------------------------------------------------------------------------------- 1 | reportType); 22 | } 23 | 24 | /** 25 | * Download the raw CSV report from AdWords and store in the object. 26 | * @return $this 27 | */ 28 | public function download() { 29 | $this->downloadRawReport(); 30 | 31 | return $this; 32 | } 33 | 34 | /** 35 | * Format the raw CSV report into a flat array. 36 | * @return $this 37 | */ 38 | public function format() { 39 | $this->formatRawReport(); 40 | 41 | return $this; 42 | } 43 | } -------------------------------------------------------------------------------- /src/Reports/KeywordsPerformanceReport.php: -------------------------------------------------------------------------------- 1 | reportType); 22 | } 23 | 24 | /** 25 | * Download the raw CSV report from AdWords and store in the object. 26 | * @return $this 27 | */ 28 | public function download() { 29 | $this->downloadRawReport(); 30 | 31 | return $this; 32 | } 33 | 34 | /** 35 | * Format the raw CSV report into a flat array. 36 | * @return $this 37 | */ 38 | public function format() { 39 | $this->formatRawReport(); 40 | 41 | return $this; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Keywords/KeywordBatchConfig.php: -------------------------------------------------------------------------------- 1 | batchSize = 2000; 28 | 29 | if (isset($config['batchSize'])) { 30 | $this->batchSize = $config['batchSize']; 31 | } 32 | } 33 | 34 | /** 35 | * Get the batch size. 36 | * @return mixed 37 | */ 38 | public function getBatchSize() { 39 | return $this->batchSize; 40 | } 41 | 42 | /** 43 | * Set the batchSize. 44 | * @param mixed $batchSize 45 | * @return KeywordBatchConfig 46 | */ 47 | public function setBatchSize($batchSize) { 48 | $this->batchSize = $batchSize; 49 | return $this; 50 | } 51 | } -------------------------------------------------------------------------------- /src/Accounts/Account.php: -------------------------------------------------------------------------------- 1 | config = $config; 18 | 19 | // Build the account service. 20 | $this->accountService = $this->adWordsServices->get($this->authObject->getSession(), ManagedCustomerService::class); 21 | $this->accounts = NULL; 22 | } 23 | 24 | /** 25 | * List all the accounts under the manager account with the given fields and predicates. 26 | * Works as an alias of "getAccounts" if the list is already downloaded before. 27 | * @return null 28 | */ 29 | public function get() { 30 | if (!$this->accounts) { 31 | $this->accounts = $this->downloadFromGoogle($this->config, $this->accountService); 32 | } 33 | 34 | return $this->accounts; 35 | } 36 | 37 | /** 38 | * @return AccountConfig 39 | */ 40 | public function getConfig() { 41 | return $this->config; 42 | } 43 | 44 | /** 45 | * @param AccountConfig $config 46 | * @return Account 47 | */ 48 | public function setConfig($config) { 49 | $this->config = $config; 50 | return $this; 51 | } 52 | 53 | /** 54 | * @return \Google\AdsApi\Common\AdsSoapClient|\Google\AdsApi\Common\SoapClient 55 | */ 56 | public function getAccountService() { 57 | return $this->accountService; 58 | } 59 | 60 | /** 61 | * @param \Google\AdsApi\Common\AdsSoapClient|\Google\AdsApi\Common\SoapClient $accountService 62 | * @return Account 63 | */ 64 | public function setAccountService($accountService) { 65 | $this->accountService = $accountService; 66 | return $this; 67 | } 68 | 69 | /** 70 | * @return null 71 | */ 72 | public function getAccounts() { 73 | return $this->accounts; 74 | } 75 | 76 | /** 77 | * @param null $accounts 78 | * @return Account 79 | */ 80 | public function setAccounts($accounts) { 81 | $this->accounts = $accounts; 82 | return $this; 83 | } 84 | } -------------------------------------------------------------------------------- /src/Reports/ReportConfig.php: -------------------------------------------------------------------------------- 1 | fields === null) { 39 | throw new Exception("Fields must be set for getting a report."); 40 | } 41 | 42 | if (isset($config['startDate'])) { 43 | $this->startDate = $config['startDate']; 44 | } 45 | 46 | if (isset($config['endDate'])) { 47 | $this->endDate = $config['endDate']; 48 | } 49 | } 50 | 51 | /** 52 | * Get the start date of the report. 53 | * @return null 54 | */ 55 | public function getStartDate() { 56 | return $this->startDate; 57 | } 58 | 59 | /** 60 | * Set the start date of the report. 61 | * @param null $startDate 62 | * @return $this 63 | */ 64 | public function setStartDate($startDate) { 65 | $this->startDate = $startDate; 66 | return $this; 67 | } 68 | 69 | /** 70 | * Get the end date of the report. 71 | * @return null 72 | */ 73 | public function getEndDate() { 74 | return $this->endDate; 75 | } 76 | 77 | /** 78 | * Set the start date of the report. 79 | * @param null $endDate 80 | * @return $this 81 | */ 82 | public function setEndDate($endDate) { 83 | $this->endDate = $endDate; 84 | return $this; 85 | } 86 | 87 | /** 88 | * Get the report predicates. 89 | * @return array 90 | */ 91 | public function getPredicates() { 92 | return $this->predicates; 93 | } 94 | 95 | /** 96 | * Set the report predicates. 97 | * @param array $predicates 98 | * @return ReportConfig 99 | */ 100 | public function setPredicates($predicates) { 101 | $this->predicates = $predicates; 102 | return $this; 103 | } 104 | } -------------------------------------------------------------------------------- /src/Keywords/KeywordBatch.php: -------------------------------------------------------------------------------- 1 | config = $config; 41 | $this->keywords = array(); 42 | $this->keywordOperations = array(); 43 | $this->operationResult = array(); 44 | } 45 | 46 | /** 47 | * Append the given config file to 48 | * @param KeywordConfig $config 49 | */ 50 | public function append(KeywordConfig $config) { 51 | $this->keywords[] = $config; 52 | $this->keywordOperations[] = $this->createKeywordOperation($config); 53 | } 54 | 55 | /** 56 | * Mutate the operations as chunks based on the given batch size. 57 | * Results of the operations are pushed into the operationResult array. 58 | */ 59 | public function mutate() { 60 | $batchOperations = array_chunk($this->keywordOperations, $this->config->getBatchSize()); 61 | foreach ($batchOperations as $operations) { 62 | $this->operationResult[] = $this->adGroupCriterionService->mutate($operations); 63 | } 64 | } 65 | 66 | /** 67 | * Get config object. 68 | * @return KeywordBatchConfig 69 | */ 70 | public function getConfig() { 71 | return $this->config; 72 | } 73 | 74 | /** 75 | * Set config object. 76 | * @param KeywordBatchConfig $config 77 | * @return KeywordBatch 78 | */ 79 | public function setConfig($config) { 80 | $this->config = $config; 81 | return $this; 82 | } 83 | 84 | /** 85 | * Get keywords. 86 | * @return array 87 | */ 88 | public function getKeywords() { 89 | return $this->keywords; 90 | } 91 | 92 | /** 93 | * Set keywords. 94 | * @param array $keywords 95 | * @return KeywordBatch 96 | */ 97 | public function setKeywords($keywords) { 98 | $this->keywords = $keywords; 99 | return $this; 100 | } 101 | 102 | /** 103 | * Get array of keyword operation objects. 104 | * @return array 105 | */ 106 | public function getKeywordOperations() { 107 | return $this->keywordOperations; 108 | } 109 | 110 | /** 111 | * Set array of keyword operation objects. 112 | * @param array $keywordOperations 113 | * @return KeywordBatch 114 | */ 115 | public function setKeywordOperations($keywordOperations) { 116 | $this->keywordOperations = $keywordOperations; 117 | return $this; 118 | } 119 | 120 | /** 121 | * Get result of the batch operation. 122 | * @return array 123 | */ 124 | public function getOperationResult() { 125 | return $this->operationResult; 126 | } 127 | 128 | /** 129 | * Set result of the batch operation. 130 | * @param array $operationResult 131 | * @return KeywordBatch 132 | */ 133 | public function setOperationResult($operationResult) { 134 | $this->operationResult = $operationResult; 135 | return $this; 136 | } 137 | } -------------------------------------------------------------------------------- /src/AdGroups/AdGroupConfig.php: -------------------------------------------------------------------------------- 1 | campaignId = $config['campaignId']; 53 | } 54 | 55 | if (isset($config['adGroupName'])) { 56 | $this->adGroupName = $config['adGroupName']; 57 | } 58 | 59 | if (isset($config['status'])) { 60 | $this->status = $config['status']; 61 | } else { 62 | $this->status = AdGroupStatus::PAUSED; 63 | } 64 | 65 | if (isset($config['bid'])) { 66 | $this->bid = $config['bid']; 67 | } 68 | } 69 | 70 | /** 71 | * Get the campaign ID. 72 | * @return mixed 73 | */ 74 | public function getCampaignId() { 75 | return $this->campaignId; 76 | } 77 | 78 | /** 79 | * Set the campaign ID. 80 | * @param mixed $campaignId 81 | * @return AdGroupConfig 82 | */ 83 | public function setCampaignId($campaignId) { 84 | $this->campaignId = $campaignId; 85 | return $this; 86 | } 87 | 88 | /** 89 | * Get the ad group name. 90 | * @return mixed 91 | */ 92 | public function getAdGroupName() { 93 | return $this->adGroupName; 94 | } 95 | 96 | /** 97 | * Set the ad group name. 98 | * @param mixed $adGroupName 99 | * @return AdGroupConfig 100 | */ 101 | public function setAdGroupName($adGroupName) { 102 | $this->adGroupName = $adGroupName; 103 | return $this; 104 | } 105 | 106 | /** 107 | * Get the ad group status. 108 | * @return mixed 109 | */ 110 | public function getStatus() { 111 | return $this->status; 112 | } 113 | 114 | /** 115 | * Set the ad group status. 116 | * @param mixed $status 117 | * @return AdGroupConfig 118 | */ 119 | public function setStatus($status) { 120 | $this->status = $status; 121 | return $this; 122 | } 123 | 124 | /** 125 | * Get the ad group bid. 126 | * @return mixed 127 | */ 128 | public function getBid() { 129 | return $this->bid; 130 | } 131 | 132 | /** 133 | * Set the ad group bid. 134 | * @param mixed $bid 135 | * @return AdGroupConfig 136 | */ 137 | public function setBid($bid) { 138 | $this->bid = $bid; 139 | return $this; 140 | } 141 | 142 | /** 143 | * Get the ad group ID. 144 | * @return mixed 145 | */ 146 | public function getAdGroupId() { 147 | return $this->adGroupId; 148 | } 149 | 150 | /** 151 | * Set the ad group ID. 152 | * @param mixed $adGroupId 153 | * @return AdGroupConfig 154 | */ 155 | public function setAdGroupId($adGroupId) { 156 | $this->adGroupId = $adGroupId; 157 | return $this; 158 | } 159 | 160 | } -------------------------------------------------------------------------------- /src/Keywords/KeywordBase.php: -------------------------------------------------------------------------------- 1 | adGroupCriterionService = $this->adWordsServices->get($this->authObject->getSession(), AdGroupCriterionService::class); 41 | } 42 | 43 | /** 44 | * Create a keyword operation based on the config. 45 | * @param KeywordConfig $config 46 | * @return AdGroupCriterionOperation 47 | * @throws Exception 48 | */ 49 | public function createKeywordOperation(KeywordConfig $config) { 50 | 51 | // Create the criterion object. 52 | $adGroupCriterionObject = new \Google\AdsApi\AdWords\v201802\cm\Keyword(); 53 | 54 | // Set the text and the match types of the criterion object. 55 | $adGroupCriterionObject->setText($config->getKeyword()); 56 | $adGroupCriterionObject->setMatchType($config->getMatchType()); 57 | 58 | // Create a new biddable ad group criterion. 59 | $adGroupCriterion = new BiddableAdGroupCriterion(); 60 | if ($config->getAdGroupId()) { 61 | $adGroupCriterion->setAdGroupId($config->getAdGroupId()); 62 | } else { 63 | throw new Exception("Ad group ID must be set in the config object in order to create a keyword."); 64 | } 65 | 66 | $adGroupCriterion->setCriterion($adGroupCriterionObject); 67 | 68 | // Set status if given in the config. 69 | if ($config->getStatus()) { 70 | $adGroupCriterion->setUserStatus($config->getStatus()); 71 | } 72 | 73 | // Set final urls if given in the config. 74 | if ($config->getFinalUrls()) { 75 | $adGroupCriterion->setFinalUrls($config->getFinalUrls()); 76 | } 77 | 78 | // Set bids if given in the config. 79 | if ($config->getBid()) { 80 | $adGroupCriterion->setBiddingStrategyConfiguration($this->setBiddingConfiguration()); 81 | } 82 | 83 | // Create the operation object. 84 | $operation = new AdGroupCriterionOperation(); 85 | $operation->setOperand($adGroupCriterion); 86 | $operation->setOperator(Operator::ADD); 87 | return $operation; 88 | } 89 | 90 | /** 91 | * Create a bidding strategy configuration object based on the config. 92 | * @return BiddingStrategyConfiguration 93 | */ 94 | private function setBiddingConfiguration() { 95 | $bid = new CpcBid(); 96 | $money = new Money(); 97 | $money->setMicroAmount($this->config->getBid() * 1000000); 98 | $bid->setBid($money); 99 | $biddingStrategyConfiguration = new BiddingStrategyConfiguration(); 100 | $biddingStrategyConfiguration->setBids([$bid]); 101 | return $biddingStrategyConfiguration; 102 | } 103 | 104 | 105 | /** 106 | * Get Ad Group Criterion Service object. 107 | * @return \Google\AdsApi\Common\AdsSoapClient|\Google\AdsApi\Common\SoapClient 108 | */ 109 | public function getAdGroupCriterionService() { 110 | return $this->adGroupCriterionService; 111 | } 112 | 113 | /** 114 | * Set Ad Group Criterion Service object. 115 | * @param \Google\AdsApi\Common\AdsSoapClient|\Google\AdsApi\Common\SoapClient $adGroupCriterionService 116 | * @return KeywordBase 117 | */ 118 | public function setAdGroupCriterionService($adGroupCriterionService) { 119 | $this->adGroupCriterionService = $adGroupCriterionService; 120 | return $this; 121 | } 122 | } -------------------------------------------------------------------------------- /src/AdWordsAuth/AdWordsAuth.php: -------------------------------------------------------------------------------- 1 | refreshToken = $refreshToken; 48 | $this->configFilePath = $configFilePath; 49 | 50 | if($refreshToken) { 51 | $this->buildOAuthToken(); 52 | } 53 | } 54 | 55 | /** 56 | * Build the oAuth object. 57 | * @return $this 58 | */ 59 | public function buildOAuthToken() { 60 | // Generate a refreshable OAuth2 credential for authentication. 61 | $oAuth = (new OAuth2TokenBuilder())->fromFile($this->configFilePath); 62 | 63 | if ($this->refreshToken) { 64 | $oAuth->withRefreshToken($this->refreshToken); 65 | } 66 | $this->oAuthCredentials = $oAuth->build(); 67 | return $this; 68 | } 69 | 70 | /** 71 | * Build an oAuth2 object for using with stateful web-app authentication process. 72 | * @param array $config 73 | * @return OAuth2 74 | */ 75 | public function buildOAuthObject(array $config){ 76 | return new OAuth2($config); 77 | } 78 | 79 | /** 80 | * Build the session object with oAuth credentials. 81 | * @param null $clientCustomerId 82 | * @return \Google\AdsApi\AdWords\AdWordsSession|mixed 83 | */ 84 | public function buildSession($clientCustomerId = NULL) { 85 | 86 | $session = (new AdWordsSessionBuilder()) 87 | ->fromFile($this->configFilePath) 88 | ->withOAuth2Credential($this->oAuthCredentials); 89 | 90 | if($clientCustomerId) { 91 | $session->withClientCustomerId($clientCustomerId); 92 | } 93 | 94 | $this->session = $session->build(); 95 | return $this; 96 | } 97 | 98 | /** 99 | * @param $serviceClass 100 | * @return \Google\AdsApi\Common\AdsSoapClient|\Google\AdsApi\Common\SoapClient 101 | */ 102 | public function getAdWordsService($serviceClass){ 103 | $service = new AdWordsServices(); 104 | $classService = $service->get($this->session, $serviceClass); 105 | return $classService; 106 | } 107 | 108 | /** 109 | * Get refresh token. 110 | * @return mixed 111 | */ 112 | public function getRefreshToken() { 113 | return $this->refreshToken; 114 | } 115 | 116 | /** 117 | * Set refresh token. 118 | * @param $refreshToken 119 | * @return $this 120 | */ 121 | public function setRefreshToken($refreshToken) { 122 | $this->refreshToken = $refreshToken; 123 | return $this; 124 | } 125 | 126 | /** 127 | * Get oAuth credentials. 128 | * @return mixed 129 | */ 130 | public function getOAuthCredentials() { 131 | return $this->oAuthCredentials; 132 | } 133 | 134 | /** 135 | * Set oAuth credentials. 136 | * @param $oAuthCredentials 137 | * @return $this 138 | */ 139 | public function setOAuthCredentials($oAuthCredentials) { 140 | $this->oAuthCredentials = $oAuthCredentials; 141 | return $this; 142 | } 143 | 144 | /** 145 | * Get AdWords session. 146 | * @return mixed 147 | */ 148 | public function getSession() { 149 | return $this->session; 150 | } 151 | 152 | /** 153 | * Set AdWords session. 154 | * @param AdWordsSession $session 155 | * @return $this 156 | */ 157 | public function setSession(AdWordsSession $session) { 158 | $this->session = $session; 159 | return $this; 160 | } 161 | } -------------------------------------------------------------------------------- /src/Keywords/Keyword.php: -------------------------------------------------------------------------------- 1 | config = $config; 40 | $this->keywords = NULL; 41 | } 42 | 43 | /** 44 | * Create a keyword based on given config. 45 | * @throws Exception 46 | */ 47 | public function create() { 48 | 49 | if (!is_array($this->config->getKeyword())) { 50 | $this->addSingleKeyword(); 51 | } else { 52 | throw new Exception("The keyword must be a single keyword, not an array. If you want to perform multiple 53 | keyword operations, use KeywordBatch object."); 54 | } 55 | } 56 | 57 | /** 58 | * List all the keywords with the given fields and predicates. 59 | * Works as an alias of "getKeywords" if the list is already downloaded before. 60 | * @return null 61 | */ 62 | public function get() { 63 | 64 | if (!$this->keywords) { 65 | $this->downloadFromGoogle($this->config, $this->adGroupCriterionService); 66 | } 67 | 68 | return $this->keywords; 69 | } 70 | 71 | /** 72 | * Remove a keyword given its keyword ID and ad group ID. 73 | * @throws Exception 74 | */ 75 | public function remove() { 76 | 77 | // Create a criterion object. 78 | $criterion = new Criterion(); 79 | 80 | // Check if the keyword ID is set. 81 | if ($this->config->getKeywordId()) { 82 | $criterion->setId($this->config->getKeywordId()); 83 | } else { 84 | throw new Exception("Keyword ID (Criterion ID) must be set in the config object in order to remove a keyword."); 85 | } 86 | 87 | // Create an ad group criterion. 88 | $adGroupCriterion = new AdGroupCriterion(); 89 | 90 | // Check if the ad group ID is set. 91 | if ($this->config->getAdGroupId()) { 92 | $adGroupCriterion->setAdGroupId($this->config->getAdGroupId()); 93 | } else { 94 | throw new Exception("Ad group ID must be set in the config object in order to remove a keyword."); 95 | } 96 | 97 | // Set the criterion on ad group object. 98 | $adGroupCriterion->setCriterion($criterion); 99 | 100 | // Create an ad group criterion operation. 101 | $operation = new AdGroupCriterionOperation(); 102 | $operation->setOperand($adGroupCriterion); 103 | $operation->setOperator(Operator::REMOVE); 104 | 105 | // Remove the criterion on the server. 106 | $this->operationResult = $this->adGroupCriterionService->mutate([$operation]); 107 | } 108 | 109 | /** 110 | * Add a single keyword based on given config. 111 | */ 112 | private function addSingleKeyword() { 113 | 114 | // Create the keyword operation. 115 | $operation = $this->createKeywordOperation($this->config); 116 | 117 | // Mutate the operation. 118 | $this->operationResult = $this->adGroupCriterionService->mutate([$operation]); 119 | } 120 | 121 | /** 122 | * Get config object. 123 | * @return KeywordConfig 124 | */ 125 | public function getConfig() { 126 | return $this->config; 127 | } 128 | 129 | /** 130 | * Set config object. 131 | * @param KeywordConfig $config 132 | * @return Keyword 133 | */ 134 | public function setConfig($config) { 135 | $this->config = $config; 136 | return $this; 137 | } 138 | 139 | /** 140 | * Get keywords. 141 | * @return null 142 | */ 143 | public function getKeywords() { 144 | return $this->keywords; 145 | } 146 | 147 | /** 148 | * Set keywords. 149 | * @param null $keywords 150 | * @return Keyword 151 | */ 152 | public function setKeywords($keywords) { 153 | $this->keywords = $keywords; 154 | return $this; 155 | } 156 | 157 | } -------------------------------------------------------------------------------- /src/Entity.php: -------------------------------------------------------------------------------- 1 | adWordsServices = new AdWordsServices(); 43 | 44 | // Create the auth object. 45 | $this->authObject = new AdWordsAuth($config->getRefreshToken(), $config->getAdwordsConfigPath()); 46 | 47 | // Build the session with the auth object. 48 | $this->authObject->buildSession($config->getClientCustomerId()); 49 | } 50 | 51 | 52 | /** 53 | * Download all the entities that meet the given config criteria and service. 54 | * Useful if the list needs to be re-downloaded. 55 | * @param Config $config 56 | * @param $adwordsService 57 | * @param $isPaginated 58 | * @return array 59 | */ 60 | public function downloadFromGoogle(Config $config, $adwordsService) { 61 | 62 | // Create a selector to select all ad groups for the specified campaign. 63 | $selector = new Selector(); 64 | $selector->setFields($config->getFields()); 65 | 66 | // Set ordering if given in config. 67 | if ($config->getOrdering()) { 68 | $selector->setOrdering($config->getOrdering()); 69 | } 70 | 71 | // Set predicates if given in config. 72 | if ($config->getPredicates()) { 73 | $selector->setPredicates($config->getPredicates()); 74 | } 75 | 76 | $result = array(); 77 | 78 | // If pagination is requested, perform it. Otherwise, perform a singular request. 79 | if ($config->isPaginated() === true) { 80 | 81 | // Set the pagination for the request. 82 | $selector->setPaging(new Paging(0, $config->getPageSize())); 83 | $totalNumEntries = 0; 84 | 85 | do { 86 | 87 | // Get a page. 88 | $page = $adwordsService->get($selector); 89 | 90 | // Get the page entries and add them to the result array. 91 | if ($page->getEntries() !== null) { 92 | $totalNumEntries = $page->getTotalNumEntries(); 93 | $result = array_merge($result, $page->getEntries()); 94 | } 95 | 96 | $selector->getPaging()->setStartIndex($selector->getPaging()->getStartIndex() + self::PAGE_LIMIT); 97 | } while ($selector->getPaging()->getStartIndex() < $totalNumEntries); 98 | } else { 99 | 100 | // Get directly. 101 | $result = $adwordsService->get($selector)->getEntries(); 102 | } 103 | 104 | return $result; 105 | } 106 | 107 | 108 | /** 109 | * Get the operation result. 110 | * @return mixed 111 | */ 112 | public function getOperationResult() { 113 | return $this->operationResult; 114 | } 115 | 116 | /** 117 | * Set the operation result. 118 | * @param mixed $operationResult 119 | * @return Entity 120 | */ 121 | public function setOperationResult($operationResult) { 122 | $this->operationResult = $operationResult; 123 | return $this; 124 | } 125 | 126 | /** 127 | * Get the auth object. 128 | * @return AdWordsAuth 129 | */ 130 | public function getAuthObject() { 131 | return $this->authObject; 132 | } 133 | 134 | /** 135 | * Set the auth object. 136 | * @param AdWordsAuth $authObject 137 | * @return Entity 138 | */ 139 | public function setAuthObject($authObject) { 140 | $this->authObject = $authObject; 141 | return $this; 142 | } 143 | 144 | /** 145 | * Get the AdWordsServices object. 146 | * @return AdWordsServices 147 | */ 148 | public function getAdWordsServices() { 149 | return $this->adWordsServices; 150 | } 151 | 152 | /** 153 | * Set the AdWordsServices object. 154 | * @param AdWordsServices $adWordsServices 155 | * @return Entity 156 | */ 157 | public function setAdWordsServices($adWordsServices) { 158 | $this->adWordsServices = $adWordsServices; 159 | return $this; 160 | } 161 | } -------------------------------------------------------------------------------- /src/Keywords/KeywordConfig.php: -------------------------------------------------------------------------------- 1 | keyword = NULL; 60 | $this->matchType = NULL; 61 | $this->finalUrls = NULL; 62 | $this->adGroupId = NULL; 63 | $this->bid = NULL; 64 | $this->status = NULL; 65 | 66 | if (isset($config['keyword'])) { 67 | $this->keyword = $config['keyword']; 68 | } 69 | 70 | if (isset($config['keywordId'])) { 71 | $this->keywordId = $config['keywordId']; 72 | } 73 | 74 | if (isset($config['matchType'])) { 75 | $this->matchType = $config['matchType']; 76 | } 77 | 78 | if (isset($config['finalUrls'])) { 79 | if (!is_array($config['finalUrls'])) { 80 | $config['finalUrls'] = [$config['finalUrls']]; 81 | } 82 | $this->finalUrls = $config['finalUrls']; 83 | } 84 | 85 | if (isset($config['adGroupId'])) { 86 | $this->adGroupId = $config['adGroupId']; 87 | } 88 | 89 | if (isset($config['bid'])) { 90 | $this->bid = $config['bid']; 91 | } 92 | 93 | if (isset($config['status'])) { 94 | $this->status = $config['status']; 95 | } 96 | 97 | } 98 | 99 | /** 100 | * Get keyword. 101 | * @return array 102 | */ 103 | public function getKeyword() { 104 | return $this->keyword; 105 | } 106 | 107 | /** 108 | * Set keyword. 109 | * @param array $keyword 110 | * @return KeywordConfig 111 | */ 112 | public function setKeyword($keyword) { 113 | $this->keyword = $keyword; 114 | return $this; 115 | } 116 | 117 | /** 118 | * Get keyword ID. 119 | * @return string 120 | */ 121 | public function getKeywordId() { 122 | return $this->keywordId; 123 | } 124 | 125 | /** 126 | * Set keyword ID. 127 | * @param string $keywordId 128 | * @return KeywordConfig 129 | */ 130 | public function setKeywordId($keywordId) { 131 | $this->keywordId = $keywordId; 132 | return $this; 133 | } 134 | 135 | /** 136 | * Get keyword match type. 137 | * @return KeywordMatchType 138 | */ 139 | public function getMatchType() { 140 | return $this->matchType; 141 | } 142 | 143 | /** 144 | * Set keyword match type. 145 | * @param KeywordMatchType $matchType 146 | * @return KeywordConfig 147 | */ 148 | public function setMatchType($matchType) { 149 | $this->matchType = $matchType; 150 | return $this; 151 | } 152 | 153 | /** 154 | * Get final URLs. 155 | * @return array 156 | */ 157 | public function getFinalUrls() { 158 | return $this->finalUrls; 159 | } 160 | 161 | /** 162 | * Set final URLs. 163 | * @param array $finalUrls 164 | * @return KeywordConfig 165 | */ 166 | public function setFinalUrls($finalUrls) { 167 | $this->finalUrls = $finalUrls; 168 | return $this; 169 | } 170 | 171 | /** 172 | * Get ad group ID. 173 | * @return string 174 | */ 175 | public function getAdGroupId() { 176 | return $this->adGroupId; 177 | } 178 | 179 | /** 180 | * Set ad group ID. 181 | * @param string $adGroupId 182 | * @return KeywordConfig 183 | */ 184 | public function setAdGroupId($adGroupId) { 185 | $this->adGroupId = $adGroupId; 186 | return $this; 187 | } 188 | 189 | /** 190 | * Get bid of the keyword. 191 | * @return int 192 | */ 193 | public function getBid() { 194 | return $this->bid; 195 | } 196 | 197 | /** 198 | * Set bid of the keyword. 199 | * @param int $bid 200 | * @return KeywordConfig 201 | */ 202 | public function setBid($bid) { 203 | $this->bid = $bid; 204 | return $this; 205 | } 206 | 207 | /** 208 | * Get status of the keyword. 209 | * @return UserStatus 210 | */ 211 | public function getStatus() { 212 | return $this->status; 213 | } 214 | 215 | /** 216 | * Set status of the keyword. 217 | * @param UserStatus $status 218 | * @return KeywordConfig 219 | */ 220 | public function setStatus($status) { 221 | $this->status = $status; 222 | return $this; 223 | } 224 | } -------------------------------------------------------------------------------- /src/AdGroups/AdGroup.php: -------------------------------------------------------------------------------- 1 | config = $config; 55 | 56 | // Build the ad group service. 57 | $this->adGroupService = $this->adWordsServices->get($this->authObject->getSession(), AdGroupService::class); 58 | $this->adGroupObject = new \Google\AdsApi\AdWords\v201802\cm\AdGroup(); 59 | $this->adGroups = NULL; 60 | } 61 | 62 | /** 63 | * Create an ad group based on given config. 64 | * @throws Exception 65 | */ 66 | public function create() { 67 | 68 | if (!$this->config->getAdGroupName()) { 69 | throw new Exception("AdGroup name must be set in the config object in order to create ad group."); 70 | } 71 | 72 | if (!$this->config->getBid()) { 73 | throw new Exception("Bid amount must be set in the config object in order to create ad group."); 74 | } 75 | 76 | if (!$this->config->getCampaignId()) { 77 | throw new Exception("Campaign ID must be set in the config object in order to create ad group."); 78 | } 79 | 80 | // Create an ad group with required settings and specified status. 81 | $this->adGroupObject->setCampaignId($this->config->getCampaignId()); 82 | $this->adGroupObject->setName($this->config->getAdGroupName()); 83 | $this->adGroupObject->setStatus($this->config->getStatus()); 84 | 85 | // Set bids. 86 | $bid = new CpcBid(); 87 | $money = new Money(); 88 | $money->setMicroAmount($this->config->getBid() * 1000000); 89 | $bid->setBid($money); 90 | $biddingStrategyConfiguration = new BiddingStrategyConfiguration(); 91 | $biddingStrategyConfiguration->setBids([$bid]); 92 | $this->adGroupObject->setBiddingStrategyConfiguration($biddingStrategyConfiguration); 93 | 94 | // Create an ad group operation and add it to the operations list. 95 | $operation = new AdGroupOperation(); 96 | $operation->setOperand($this->adGroupObject); 97 | $operation->setOperator(Operator::ADD); 98 | 99 | // Create the ad groups on the server. 100 | $result = $this->adGroupService->mutate([$operation]); 101 | $this->operationResult = $result->getValue(); 102 | } 103 | 104 | /** 105 | * List all the ad groups with the given fields and predicates. 106 | * Works as an alias of "getAdGroups" if the list is already downloaded before. 107 | * @return null 108 | */ 109 | public function get() { 110 | if (!$this->adGroups) { 111 | $this->adGroups = $this->downloadFromGoogle($this->config, $this->adGroupService); 112 | } 113 | 114 | return $this->adGroups; 115 | } 116 | 117 | /** 118 | * Remove an ad group given its ad group ID. 119 | * @throws Exception 120 | */ 121 | public function remove() { 122 | 123 | if (!$this->config->getAdGroupId()) { 124 | throw new Exception("Ad group ID must be set in the config object in order to remove an ad group."); 125 | } 126 | 127 | // Create ad group with REMOVED status. 128 | $this->adGroupObject->setId($this->config->getAdGroupId()); 129 | $this->adGroupObject->setStatus(AdGroupStatus::REMOVED); 130 | 131 | // Create ad group operation and add it to the list. 132 | $operation = new AdGroupOperation(); 133 | $operation->setOperand($this->adGroupObject); 134 | $operation->setOperator(Operator::SET); 135 | 136 | // Remove the ad group on the server. 137 | $result = $this->adGroupService->mutate([$operation]); 138 | $this->operationResult = $result->getValue()[0]; 139 | } 140 | 141 | /** 142 | * Get the config object. 143 | * @return AdGroupConfig 144 | */ 145 | public function getConfig() { 146 | return $this->config; 147 | } 148 | 149 | /** 150 | * Set the config object. 151 | * @param AdGroupConfig $config 152 | * @return AdGroup 153 | */ 154 | public function setConfig($config) { 155 | $this->config = $config; 156 | return $this; 157 | } 158 | 159 | /** 160 | * Get the list of ad groups. 161 | * @return null 162 | */ 163 | public function getAdGroups() { 164 | return $this->adGroups; 165 | } 166 | 167 | /** 168 | * Get the list of ad groups. 169 | * @param null $adGroups 170 | * @return AdGroup 171 | */ 172 | public function setAdGroups($adGroups) { 173 | $this->adGroups = $adGroups; 174 | return $this; 175 | } 176 | 177 | /** 178 | * Get the AdGroupService object. 179 | * @return \Google\AdsApi\Common\AdsSoapClient|\Google\AdsApi\Common\SoapClient 180 | */ 181 | public function getAdGroupService() { 182 | return $this->adGroupService; 183 | } 184 | 185 | /** 186 | * Set the AdGroupService object. 187 | * @param \Google\AdsApi\Common\AdsSoapClient|\Google\AdsApi\Common\SoapClient $adGroupService 188 | * @return AdGroup 189 | */ 190 | public function setAdGroupService($adGroupService) { 191 | $this->adGroupService = $adGroupService; 192 | return $this; 193 | } 194 | 195 | } -------------------------------------------------------------------------------- /src/Config.php: -------------------------------------------------------------------------------- 1 | refreshToken = NULL; 59 | $this->clientCustomerId = NULL; 60 | $this->adwordsConfigPath = NULL; 61 | $this->fields = NULL; 62 | $this->predicates = NULL; 63 | $this->ordering = NULL; 64 | $this->paginated = false; 65 | $this->pageSize = self::PAGE_SIZE; 66 | 67 | if (isset($config['refreshToken'])) { 68 | $this->refreshToken = $config['refreshToken']; 69 | } else { 70 | throw new \Exception("Refresh token must be set in config array."); 71 | } 72 | 73 | if (isset($config['clientCustomerId'])) { 74 | $this->clientCustomerId = $config['clientCustomerId']; 75 | } else { 76 | throw new \Exception("Client customer ID must be set in config array."); 77 | } 78 | 79 | if (isset($config['adwordsConfigPath'])) { 80 | $this->adwordsConfigPath = $config['adwordsConfigPath']; 81 | } 82 | 83 | if (isset($config['fields'])) { 84 | $this->fields = $config['fields']; 85 | } 86 | 87 | if (isset($config['predicates'])) { 88 | if (!is_array($config['predicates'])) { 89 | $config['predicates'] = [$config['predicates']]; 90 | } 91 | 92 | $this->predicates = $config['predicates']; 93 | } 94 | 95 | if (isset($config['ordering'])) { 96 | if (!is_array($config['ordering'])) { 97 | $config['ordering'] = [$config['ordering']]; 98 | } 99 | 100 | $this->predicates = $config['ordering']; 101 | } 102 | 103 | if (isset($config['paginated']) AND $config['paginated'] == true) { 104 | $this->paginated = $config['paginated']; 105 | } 106 | 107 | if (isset($config['pageSize'])) { 108 | $this->pageSize = $config['pageSize']; 109 | } 110 | } 111 | 112 | 113 | /** 114 | * Get the refresh token. 115 | * @return string 116 | */ 117 | public function getRefreshToken() { 118 | return $this->refreshToken; 119 | } 120 | 121 | /** 122 | * Set the refresh token. 123 | * @param string $refreshToken 124 | * @return Config 125 | */ 126 | public function setRefreshToken($refreshToken) { 127 | $this->refreshToken = $refreshToken; 128 | return $this; 129 | } 130 | 131 | /** 132 | * Get the client customer ID. 133 | * @return string 134 | */ 135 | public function getClientCustomerId() { 136 | return $this->clientCustomerId; 137 | } 138 | 139 | /** 140 | * Set the client customer ID. 141 | * @param string $clientCustomerId 142 | * @return Config 143 | */ 144 | public function setClientCustomerId($clientCustomerId) { 145 | $this->clientCustomerId = $clientCustomerId; 146 | return $this; 147 | } 148 | 149 | /** 150 | * Get the AdWords config file path. 151 | * @return mixed 152 | */ 153 | public function getAdwordsConfigPath() { 154 | return $this->adwordsConfigPath; 155 | } 156 | 157 | /** 158 | * Set the AdWords config file path. 159 | * @param mixed $adwordsConfigPath 160 | * @return Config 161 | */ 162 | public function setAdwordsConfigPath($adwordsConfigPath) { 163 | $this->adwordsConfigPath = $adwordsConfigPath; 164 | return $this; 165 | } 166 | 167 | /** 168 | * Set the fields. 169 | * @return mixed 170 | */ 171 | public function getFields() { 172 | return $this->fields; 173 | } 174 | 175 | /** 176 | * Get the fields. 177 | * @param mixed $fields 178 | * @return Config 179 | */ 180 | public function setFields($fields) { 181 | $this->fields = $fields; 182 | return $this; 183 | } 184 | 185 | /** 186 | * Get the predicates. 187 | * @return array|mixed 188 | */ 189 | public function getPredicates() { 190 | return $this->predicates; 191 | } 192 | 193 | /** 194 | * Set the predicates. 195 | * @param array|mixed $predicates 196 | * @return Config 197 | */ 198 | public function setPredicates($predicates) { 199 | $this->predicates = $predicates; 200 | return $this; 201 | } 202 | 203 | /** 204 | * Add an individual predicate to predicates. 205 | * @param $predicate 206 | */ 207 | public function addPredicate($predicate) { 208 | $this->predicates[] = $predicate; 209 | } 210 | 211 | /** 212 | * Get the ordering. 213 | * @return mixed 214 | */ 215 | public function getOrdering() { 216 | return $this->ordering; 217 | } 218 | 219 | /** 220 | * Set the ordering. 221 | * @param mixed $ordering 222 | * @return Config 223 | */ 224 | public function setOrdering($ordering) { 225 | $this->ordering = $ordering; 226 | return $this; 227 | } 228 | 229 | /** 230 | * @return boolean 231 | */ 232 | public function isPaginated() { 233 | return $this->paginated; 234 | } 235 | 236 | /** 237 | * @param boolean $paginated 238 | * @return Config 239 | */ 240 | public function setPaginated($paginated) { 241 | $this->paginated = $paginated; 242 | return $this; 243 | } 244 | 245 | /** 246 | * @return int 247 | */ 248 | public function getPageSize() { 249 | return $this->pageSize; 250 | } 251 | 252 | /** 253 | * @param int $pageSize 254 | * @return Config 255 | */ 256 | public function setPageSize($pageSize) { 257 | $this->pageSize = $pageSize; 258 | return $this; 259 | } 260 | 261 | } -------------------------------------------------------------------------------- /src/Reports/Report.php: -------------------------------------------------------------------------------- 1 | config = $config; 53 | $this->reportType = $reportType; 54 | 55 | return $this; 56 | } 57 | 58 | /** 59 | * Downloads the raw report as string. 60 | * @return $this 61 | */ 62 | protected function downloadRawReport() { 63 | 64 | // Get the report object from AdWords. 65 | $reportDownloadResult = $this->downloadReportFromAdWords($this->reportType); 66 | 67 | // Save the string version. 68 | $this->report = $reportDownloadResult->getAsString(); 69 | 70 | return $this; 71 | } 72 | 73 | /** 74 | * Formats the report into a simple one-dimensional array. 75 | * Works directly on the report object for memory optimization. 76 | * @return $this 77 | */ 78 | public function formatRawReport() { 79 | 80 | // Get the rows as array and split the headers from the report. 81 | $this->report = explode(PHP_EOL, $this->report); 82 | $this->reportHeaders = str_getcsv(array_shift($this->report)); 83 | 84 | // Convert each line of the CSV to array. 85 | foreach ($this->report as $key => $item) { 86 | if ($item !== '') { 87 | $this->report[$key] = str_getcsv($item); 88 | } else { 89 | unset($this->report[$key]); 90 | } 91 | } 92 | 93 | return $this; 94 | } 95 | 96 | /** 97 | * Saves the report CSV to a given file. 98 | * @param $filePath 99 | * @return $this 100 | */ 101 | public function saveToFile($filePath) { 102 | $this->file_force_contents($filePath, $this->report); 103 | $this->filePath = $filePath; 104 | 105 | return $this; 106 | } 107 | 108 | /** 109 | * Download report from AdWords and write it to the given file. 110 | * However, it does not store the report, just writes the contents to the file. 111 | * @param $filePath 112 | */ 113 | public function downloadToFile($filePath) { 114 | 115 | // Create the missing folders in the file path. 116 | $this->createMissingFolders($filePath); 117 | 118 | // Get the report object from AdWords. 119 | $reportDownloadResult = $this->downloadReportFromAdWords($this->reportType); 120 | $reportDownloadResult->saveToFile($filePath); 121 | } 122 | 123 | /** 124 | * Downloads the result from Google AdWords. 125 | * @param $reportType 126 | * @return \Google\AdsApi\AdWords\Reporting\ReportDownloadResult 127 | */ 128 | private function downloadReportFromAdWords($reportType) { 129 | // Create the auth object. 130 | $authObject = new AdWordsAuth($this->config->getRefreshToken(), $this->config->getAdwordsConfigPath()); 131 | 132 | // Build the session with the auth object. 133 | $authObject->buildSession($this->config->getClientCustomerId()); 134 | 135 | // Create report date range object. 136 | $reportDates = new DateRange($this->config->getStartDate(), $this->config->getEndDate()); 137 | 138 | // Create selector. 139 | $selector = new Selector(); 140 | $selector->setFields($this->config->getFields()); 141 | $selector->setDateRange($reportDates); 142 | 143 | if (!empty($this->config->getPredicates())) { 144 | $selector->setPredicates($this->config->getPredicates()); 145 | } 146 | 147 | // Create report definition. 148 | $reportDefinition = new ReportDefinition(); 149 | $reportDefinition->setSelector($selector); 150 | $reportDefinition->setReportName('AdProReport'); 151 | $reportDefinition->setDateRangeType(ReportDefinitionDateRangeType::CUSTOM_DATE); 152 | $reportDefinition->setReportType($reportType); 153 | $reportDefinition->setDownloadFormat(DownloadFormat::CSV); 154 | 155 | // Download report. 156 | $reportDownloader = new ReportDownloader($authObject->getSession()); 157 | 158 | return $reportDownloader->downloadReport($reportDefinition); 159 | } 160 | 161 | /** 162 | * Get report config. 163 | * @return ReportConfig 164 | */ 165 | public function getConfig() { 166 | return $this->config; 167 | } 168 | 169 | /** 170 | * Set report config. 171 | * @param ReportConfig $config 172 | * @return Report 173 | */ 174 | public function setConfig($config) { 175 | $this->config = $config; 176 | 177 | return $this; 178 | } 179 | 180 | /** 181 | * Get the report result. 182 | * @return array|string 183 | */ 184 | public function getReport() { 185 | return $this->report; 186 | } 187 | 188 | /** 189 | * Set the report result. 190 | * @param array|string $report 191 | * @return Report 192 | */ 193 | public function setReport($report) { 194 | $this->report = $report; 195 | 196 | return $this; 197 | } 198 | 199 | /** 200 | * Get the report headers. 201 | * @return array 202 | */ 203 | public function getReportHeaders() { 204 | return $this->reportHeaders; 205 | } 206 | 207 | /** 208 | * Set the report headers. 209 | * @param array $reportHeaders 210 | * @return Report 211 | */ 212 | public function setReportHeaders($reportHeaders) { 213 | $this->reportHeaders = $reportHeaders; 214 | 215 | return $this; 216 | } 217 | 218 | /** 219 | * @return mixed 220 | */ 221 | public function getFilePath() { 222 | return $this->filePath; 223 | } 224 | 225 | /** 226 | * @param mixed $filePath 227 | * @return Report 228 | */ 229 | public function setFilePath($filePath) { 230 | $this->filePath = $filePath; 231 | 232 | return $this; 233 | } 234 | 235 | /** 236 | * @return mixed 237 | */ 238 | public function getReportType() { 239 | return $this->reportType; 240 | } 241 | 242 | /** 243 | * @param mixed $reportType 244 | * @return Report 245 | */ 246 | public function setReportType($reportType) { 247 | $this->reportType = $reportType; 248 | 249 | return $this; 250 | } 251 | 252 | /** 253 | * An alias to the getReport method. 254 | * @return array|string 255 | */ 256 | public function get() { 257 | return $this->report; 258 | } 259 | 260 | /** 261 | * Creates required directories if they are not set. 262 | * Taken from http://php.net/manual/en/function.file-put-contents.php#84180 263 | * @param $filePath 264 | * @param $contents 265 | */ 266 | private function file_force_contents($filePath, $contents) { 267 | $this->createMissingFolders($filePath); 268 | file_put_contents($filePath, $contents); 269 | } 270 | 271 | private function createMissingFolders($path) { 272 | $directories = explode('/', $path); 273 | $fileName = array_pop($directories); 274 | $path = implode('/', $directories); 275 | if (!is_dir($path)) { 276 | mkdir($path, 0, true); 277 | } 278 | } 279 | 280 | } -------------------------------------------------------------------------------- /docs/diagrams/EasyAdwords_ClassDiagram.uml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \EasyAdwords\Base 5 | 6 | \EasyAdwords\Reports\CampaignPerformanceReport 7 | \EasyAdwords\Reports\KeywordsPerformanceReport 8 | \EasyAdwords\Keywords\KeywordBatch 9 | \EasyAdwords\Keywords\KeywordConfig 10 | \EasyAdwords\Reports\ReportInterface 11 | \EasyAdwords\Campaigns\Campaign 12 | \App\AdPro\Reports\SearchQueryPerformanceReport 13 | \EasyAdwords\Config 14 | \EasyAdwords\Campaigns\CampaignConfig 15 | \EasyAdwords\Entity 16 | \EasyAdwords\Keywords\KeywordBase 17 | \EasyAdwords\AdGroups\AdGroup 18 | \EasyAdwords\AdGroups\AdGroupConfig 19 | \EasyAdwords\Reports\AdPerformanceReport 20 | \EasyAdwords\Reports\AccountPerformanceReport 21 | \EasyAdwords\Reports\Report 22 | \EasyAdwords\Keywords\Keyword 23 | \EasyAdwords\Reports\AdGroupPerformanceReport 24 | \EasyAdwords\Reports\FinalUrlReport 25 | \EasyAdwords\Reports\ReportConfig 26 | \EasyAdwords\Base 27 | \EasyAdwords\Keywords\KeywordBatchConfig 28 | \EasyAdwords\Auth\AdWordsAuth 29 | \EasyAdwords\EntityInterface 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | Fields 214 | Methods 215 | 216 | private 217 | 218 | 219 | -------------------------------------------------------------------------------- /src/Campaigns/Campaign.php: -------------------------------------------------------------------------------- 1 | config = $config; 59 | 60 | // Build the campaign service. 61 | $this->campaignService = $this->adWordsServices->get($this->authObject->getSession(), CampaignService::class); 62 | 63 | // Build the singular campaign object. 64 | $this->campaignObject = new \Google\AdsApi\AdWords\v201802\cm\Campaign(); 65 | $this->campaigns = NULL; 66 | } 67 | 68 | /** 69 | * Create a campaign based on given config information. 70 | * @throws Exception 71 | */ 72 | public function create() { 73 | 74 | // Check if the given configuration is correct to create a campaign. 75 | $this->checkCreateConfig(); 76 | 77 | // Create a campaign with given settings. 78 | $this->campaignObject->setName($this->config->getCampaignName()); 79 | $this->campaignObject->setAdvertisingChannelType($this->config->getAdvertisingChannelType()); 80 | 81 | // Set shared budget (required). 82 | $this->createBudget(); 83 | 84 | // Set the bidding strategy. 85 | $this->setBiddingStrategyObject(); 86 | 87 | // Set network targeting. 88 | $this->setNetworkTargetingObject(); 89 | 90 | // Set additional settings (optional). 91 | $this->campaignObject->setStatus($this->config->getStatus()); 92 | $this->campaignObject->setStartDate($this->config->getStartDate()); 93 | $this->campaignObject->setEndDate($this->config->getEndDate()); 94 | $this->campaignObject->setAdServingOptimizationStatus($this->config->getAdServingOptimizationStatus()); 95 | $this->campaignObject->setServingStatus($this->config->getServingStatus()); 96 | 97 | // Create a campaign operation and add it to the operations list. 98 | $operation = new CampaignOperation(); 99 | $operation->setOperand($this->campaignObject); 100 | $operation->setOperator(Operator::ADD); 101 | 102 | // Create the campaigns on the server. 103 | $result = $this->campaignService->mutate([$operation]); 104 | $this->operationResult = $result->getValue(); 105 | return $this; 106 | } 107 | 108 | /** 109 | * List all the campaigns with the given fields and predicates. 110 | * Works as an alias of "getCampaigns" if the list is already downloaded before. 111 | * @param bool $isPaginated 112 | * @return array|mixed|null 113 | */ 114 | public function get() { 115 | 116 | // If the campaigns are not already downloaded, download them. 117 | if (!$this->campaigns) { 118 | $this->campaigns = $this->downloadFromGoogle($this->config, $this->campaignService); 119 | } 120 | 121 | return $this->campaigns; 122 | } 123 | 124 | /** 125 | * Remove a campaign given its campaign ID. 126 | * @throws Exception 127 | */ 128 | public function remove() { 129 | 130 | if (!$this->config->getCampaignId()) { 131 | throw new Exception("Campaign ID must be set in the config object in order to remove a campaign."); 132 | } 133 | 134 | // Identify the campaign. 135 | $this->campaignObject->setId($this->config->getCampaignId()); 136 | $this->campaignObject->setStatus(CampaignStatus::REMOVED); 137 | 138 | // Create a campaign operation and add it to the list. 139 | $operation = new CampaignOperation(); 140 | $operation->setOperand($this->campaignObject); 141 | $operation->setOperator(Operator::SET); 142 | 143 | // Remove the campaign on the server. 144 | $result = $this->campaignService->mutate([$operation]); 145 | $this->operationResult = $result->getValue()[0]; 146 | } 147 | 148 | private function checkCreateConfig() { 149 | if (!$this->config->getCampaignName()) { 150 | throw new Exception("Campaign name must be set in the config object in order to create campaign."); 151 | } 152 | if($this->config->getAdvertisingChannelType()) { 153 | throw new Exception('Advertising channel type must be set in order to create a campaign.'); 154 | } 155 | if($this->config->getStatus()) { 156 | throw new Exception('Campaign status must be set in order to create a campaign.'); 157 | } 158 | if($this->config->getBudget()) { 159 | throw new Exception('Budget must be set in order to create a campaign.'); 160 | } 161 | if($this->config->getBiddingStrategyType()) { 162 | throw new Exception('Bidding strategy must be set in order to create a campaign.'); 163 | } 164 | if($this->config->getBudgetDeliveryMethod()) { 165 | throw new Exception('Budget delivery method must be set in order to create a campaign.'); 166 | } 167 | if($this->config->getTargetGoogleSearch()) { 168 | throw new Exception('Target Google Search must be set as boolean in order to create a campaign.'); 169 | } 170 | if($this->config->getTargetSearchNetwork()) { 171 | throw new Exception('Target Search Network must be set as boolean in order to create a campaign.'); 172 | } 173 | if($this->config->getTargetContentNetwork()) { 174 | throw new Exception('Target Content Network must be set as boolean in order to create a campaign.'); 175 | } 176 | if($this->config->getStartDate()) { 177 | throw new Exception('Start Date must be set in order to create a campaign.'); 178 | } 179 | if($this->config->getServingStatus()) { 180 | throw new Exception('Serving status must be set in order to create a campaign.'); 181 | } 182 | } 183 | 184 | /** 185 | * Create the budget object and apply the budget to the campaign object. 186 | */ 187 | private function createBudget() { 188 | 189 | // Create the budget service. 190 | $budgetService = $this->adWordsServices->get($this->authObject->getSession(), BudgetService::class); 191 | 192 | // Create the shared budget. 193 | $money = new Money(); 194 | $money->setMicroAmount($this->config->getBudget() * 1000000); 195 | $budget = new Budget(); 196 | $budget->setName($this->config->getBudgetName()); 197 | $budget->setAmount($money); 198 | $budget->setDeliveryMethod($this->config->getBudgetDeliveryMethod()); 199 | 200 | // Create a budget operation. 201 | $operation = new BudgetOperation(); 202 | $operation->setOperand($budget); 203 | $operation->setOperator(Operator::ADD); 204 | 205 | // Create the budget on the server. 206 | $result = $budgetService->mutate([$operation]); 207 | $budget = $result->getValue()[0]; 208 | 209 | // Apply the budget to the campaign object. 210 | $this->campaignObject->setBudget(new Budget()); 211 | $this->campaignObject->getBudget()->setBudgetId($budget->getBudgetId()); 212 | } 213 | 214 | /** 215 | * Create the network setting object and apply the settings to the campaign object. 216 | */ 217 | private function setNetworkTargetingObject() { 218 | $networkSetting = new NetworkSetting(); 219 | $networkSetting->setTargetGoogleSearch($this->config->getTargetGoogleSearch()); 220 | $networkSetting->setTargetSearchNetwork($this->config->getTargetSearchNetwork()); 221 | $networkSetting->setTargetContentNetwork($this->config->getTargetContentNetwork()); 222 | 223 | // Apply the targeting to the campaign object. 224 | $this->campaignObject->setNetworkSetting($networkSetting); 225 | } 226 | 227 | /** 228 | * Create the bidding strategy object and apply the strategy to the campaign object. 229 | */ 230 | private function setBiddingStrategyObject() { 231 | 232 | // Set bidding strategy (required). 233 | $biddingStrategyConfiguration = new BiddingStrategyConfiguration(); 234 | $biddingStrategyConfiguration->setBiddingStrategyType($this->config->getBiddingStrategyType()); 235 | 236 | // Apply the strategy to the campaign object. 237 | $this->campaignObject->setBiddingStrategyConfiguration($biddingStrategyConfiguration); 238 | } 239 | 240 | /** 241 | * Get campaign object. 242 | * @return \Google\AdsApi\AdWords\v201802\cm\Campaign 243 | */ 244 | public function getCampaignObject() { 245 | return $this->campaignObject; 246 | } 247 | 248 | /** 249 | * Set campaign object. 250 | * @param \Google\AdsApi\AdWords\v201802\cm\Campaign $campaignObject 251 | * @return Campaign 252 | */ 253 | public function setCampaignObject($campaignObject) { 254 | $this->campaignObject = $campaignObject; 255 | return $this; 256 | } 257 | 258 | /** 259 | * Get config. 260 | * @return CampaignConfig 261 | */ 262 | public function getConfig() { 263 | return $this->config; 264 | } 265 | 266 | /** 267 | * Set config. 268 | * @param CampaignConfig $config 269 | * @return Campaign 270 | */ 271 | public function setConfig($config) { 272 | $this->config = $config; 273 | return $this; 274 | } 275 | 276 | /** 277 | * Get auth object. 278 | * @return AdWordsAuth 279 | */ 280 | public function getAuthObject() { 281 | return $this->authObject; 282 | } 283 | 284 | /** 285 | * Set auth object. 286 | * @param AdWordsAuth $authObject 287 | * @return Campaign 288 | */ 289 | public function setAuthObject($authObject) { 290 | $this->authObject = $authObject; 291 | return $this; 292 | } 293 | 294 | /** 295 | * Get AdWords service. 296 | * @return AdWordsServices 297 | */ 298 | public function getAdWordsServices() { 299 | return $this->adWordsServices; 300 | } 301 | 302 | /** 303 | * Set AdWords service. 304 | * @param AdWordsServices $adWordsServices 305 | * @return Campaign 306 | */ 307 | public function setAdWordsServices($adWordsServices) { 308 | $this->adWordsServices = $adWordsServices; 309 | return $this; 310 | } 311 | 312 | /** 313 | * Get campaign service. 314 | * @return \Google\AdsApi\Common\AdsSoapClient|\Google\AdsApi\Common\SoapClient 315 | */ 316 | public function getCampaignService() { 317 | return $this->campaignService; 318 | } 319 | 320 | /** 321 | * Set campaign service. 322 | * @param \Google\AdsApi\Common\AdsSoapClient|\Google\AdsApi\Common\SoapClient $campaignService 323 | * @return Campaign 324 | */ 325 | public function setCampaignService($campaignService) { 326 | $this->campaignService = $campaignService; 327 | return $this; 328 | } 329 | 330 | /** 331 | * Get campaigns. 332 | * @return null|array 333 | */ 334 | public function getCampaigns() { 335 | return $this->campaigns; 336 | } 337 | 338 | /** 339 | * Set campaigns. 340 | * @param null $campaigns 341 | * @return Campaign 342 | */ 343 | public function setCampaigns($campaigns) { 344 | $this->campaigns = $campaigns; 345 | return $this; 346 | } 347 | 348 | } -------------------------------------------------------------------------------- /src/Campaigns/CampaignConfig.php: -------------------------------------------------------------------------------- 1 | campaignName = NULL; 107 | $this->advertisingChannelType = NULL; 108 | $this->status = NULL; 109 | $this->budget = NULL; 110 | $this->budgetName = NULL; 111 | $this->biddingStrategyType = NULL; 112 | $this->budgetDeliveryMethod = NULL; 113 | $this->targetGoogleSearch = NULL; 114 | $this->targetSearchNetwork = NULL; 115 | $this->targetContentNetwork = NULL; 116 | $this->startDate = NULL; 117 | $this->endDate = NULL; 118 | $this->adServingOptimizationStatus = NULL; 119 | $this->servingStatus = NULL; 120 | $this->campaignId = NULL; 121 | 122 | // If the 'useDefaults' option is given, set the defaults. 123 | if(isset($config['useDefaults']) && $config['useDefaults'] === true) { 124 | 125 | // Predefined defaults. 126 | $this->campaignName = NULL; 127 | $this->advertisingChannelType = AdvertisingChannelType::SEARCH; 128 | $this->status = CampaignStatus::PAUSED; 129 | $this->budget = 50; 130 | $this->budgetName = "EasyAdWords Budget #" . uniqid(); 131 | $this->biddingStrategyType = BiddingStrategyType::MANUAL_CPC; 132 | $this->budgetDeliveryMethod = BudgetBudgetDeliveryMethod::STANDARD; 133 | $this->targetGoogleSearch = true; 134 | $this->targetSearchNetwork = true; 135 | $this->targetContentNetwork = true; 136 | $this->startDate = date('Ymd'); 137 | $this->servingStatus = ServingStatus::SERVING; 138 | } 139 | 140 | if (isset($config['campaignName'])) { 141 | $this->campaignName = $config['campaignName']; 142 | } 143 | 144 | if (isset($config['campaignId'])) { 145 | $this->campaignId = $config['campaignId']; 146 | $this->addPredicate(new Predicate('Id', PredicateOperator::EQUALS, [$this->campaignId])); 147 | } 148 | 149 | if (isset($config['advertisingChannelType'])) { 150 | $this->advertisingChannelType = $config['advertisingChannelType']; 151 | } 152 | 153 | if (isset($config['status'])) { 154 | $this->status = $config['status']; 155 | } 156 | 157 | if (isset($config['budget'])) { 158 | $this->budget = $config['budget']; 159 | } 160 | 161 | if (isset($config['biddingStrategyType'])) { 162 | $this->biddingStrategyType = $config['biddingStrategyType']; 163 | } 164 | 165 | if (isset($config['budgetDeliveryMethod'])) { 166 | $this->budgetDeliveryMethod = $config['budgetDeliveryMethod']; 167 | } 168 | 169 | if (isset($config['targetGoogleSearch'])) { 170 | $this->targetGoogleSearch = $config['targetGoogleSearch']; 171 | } 172 | 173 | if (isset($config['targetSearchNetwork'])) { 174 | $this->targetSearchNetwork = $config['targetSearchNetwork']; 175 | } 176 | 177 | if (isset($config['targetContentNetwork'])) { 178 | $this->targetContentNetwork = $config['targetContentNetwork']; 179 | } 180 | 181 | if (isset($config['startDate'])) { 182 | $this->startDate = date('Ymd', strtotime($config['startDate'])); 183 | } 184 | 185 | if (isset($config['endDate'])) { 186 | $this->endDate = date('Ymd', strtotime($config['endDate'])); 187 | } 188 | 189 | if (isset($config['adServingOptimizationStatus'])) { 190 | $this->adServingOptimizationStatus = $config['adServingOptimizationStatus']; 191 | } 192 | } 193 | 194 | 195 | /** 196 | * Get the advertising channel type. 197 | * @return mixed 198 | */ 199 | public function getAdvertisingChannelType() { 200 | return $this->advertisingChannelType; 201 | } 202 | 203 | /** 204 | * Set the advertising channel type. 205 | * @param mixed $advertisingChannelType 206 | * @return CampaignConfig 207 | */ 208 | public function setAdvertisingChannelType($advertisingChannelType) { 209 | $this->advertisingChannelType = $advertisingChannelType; 210 | return $this; 211 | } 212 | 213 | /** 214 | * Get the status of the campaign. 215 | * @return mixed 216 | */ 217 | public function getStatus() { 218 | return $this->status; 219 | } 220 | 221 | /** 222 | * Set the status of the campaign. 223 | * @param mixed $status 224 | * @return CampaignConfig 225 | */ 226 | public function setStatus($status) { 227 | $this->status = $status; 228 | return $this; 229 | } 230 | 231 | /** 232 | * Get the budget of the campaign. 233 | * @return mixed 234 | */ 235 | public function getBudget() { 236 | return $this->budget; 237 | } 238 | 239 | /** 240 | * Set the budget of the campaign. 241 | * @param mixed $budget 242 | * @return CampaignConfig 243 | */ 244 | public function setBudget($budget) { 245 | $this->budget = $budget; 246 | return $this; 247 | } 248 | 249 | /** 250 | * Get the budget name. 251 | * @return string 252 | */ 253 | public function getBudgetName() { 254 | return $this->budgetName; 255 | } 256 | 257 | /** 258 | * Set the budget name. 259 | * @param string $budgetName 260 | * @return CampaignConfig 261 | */ 262 | public function setBudgetName($budgetName) { 263 | $this->budgetName = $budgetName; 264 | return $this; 265 | } 266 | 267 | /** 268 | * Get the bidding strategy type. 269 | * @return mixed 270 | */ 271 | public function getBiddingStrategyType() { 272 | return $this->biddingStrategyType; 273 | } 274 | 275 | /** 276 | * Set the bidding strategy type. 277 | * @param mixed $biddingStrategyType 278 | * @return CampaignConfig 279 | */ 280 | public function setBiddingStrategyType($biddingStrategyType) { 281 | $this->biddingStrategyType = $biddingStrategyType; 282 | return $this; 283 | } 284 | 285 | /** 286 | * Get the budget delivery method. 287 | * @return mixed 288 | */ 289 | public function getBudgetDeliveryMethod() { 290 | return $this->budgetDeliveryMethod; 291 | } 292 | 293 | /** 294 | * Set the budget delivery method. 295 | * @param mixed $budgetDeliveryMethod 296 | * @return CampaignConfig 297 | */ 298 | public function setBudgetDeliveryMethod($budgetDeliveryMethod) { 299 | $this->budgetDeliveryMethod = $budgetDeliveryMethod; 300 | return $this; 301 | } 302 | 303 | /** 304 | * Get the target google search value. 305 | * @return mixed 306 | */ 307 | public function getTargetGoogleSearch() { 308 | return $this->targetGoogleSearch; 309 | } 310 | 311 | /** 312 | * Set the target google search value. 313 | * @param mixed $targetGoogleSearch 314 | * @return CampaignConfig 315 | */ 316 | public function setTargetGoogleSearch($targetGoogleSearch) { 317 | $this->targetGoogleSearch = $targetGoogleSearch; 318 | return $this; 319 | } 320 | 321 | /** 322 | * Get the target search network value. 323 | * @return mixed 324 | */ 325 | public function getTargetSearchNetwork() { 326 | return $this->targetSearchNetwork; 327 | } 328 | 329 | /** 330 | * Set the target search network value. 331 | * @param mixed $targetSearchNetwork 332 | * @return CampaignConfig 333 | */ 334 | public function setTargetSearchNetwork($targetSearchNetwork) { 335 | $this->targetSearchNetwork = $targetSearchNetwork; 336 | return $this; 337 | } 338 | 339 | /** 340 | * Get the target content network value. 341 | * @return mixed 342 | */ 343 | public function getTargetContentNetwork() { 344 | return $this->targetContentNetwork; 345 | } 346 | 347 | /** 348 | * Set the target content network value. 349 | * @param mixed $targetContentNetwork 350 | * @return CampaignConfig 351 | */ 352 | public function setTargetContentNetwork($targetContentNetwork) { 353 | $this->targetContentNetwork = $targetContentNetwork; 354 | return $this; 355 | } 356 | 357 | /** 358 | * Get the start date of the campaign. 359 | * @return false|string 360 | */ 361 | public function getStartDate() { 362 | return $this->startDate; 363 | } 364 | 365 | /** 366 | * Set the start date of the campaign. 367 | * @param false|string $startDate 368 | * @return CampaignConfig 369 | */ 370 | public function setStartDate($startDate) { 371 | $this->startDate = $startDate; 372 | return $this; 373 | } 374 | 375 | /** 376 | * Get the end date of the campaign. 377 | * @return false|string 378 | */ 379 | public function getEndDate() { 380 | return $this->endDate; 381 | } 382 | 383 | /** 384 | * Set the end date of the campaign. 385 | * @param false|string $endDate 386 | * @return CampaignConfig 387 | */ 388 | public function setEndDate($endDate) { 389 | $this->endDate = $endDate; 390 | return $this; 391 | } 392 | 393 | /** 394 | * Get the ad serving optimization status. 395 | * @return mixed 396 | */ 397 | public function getAdServingOptimizationStatus() { 398 | return $this->adServingOptimizationStatus; 399 | } 400 | 401 | /** 402 | * Set the ad serving optimization status. 403 | * @param mixed $adServingOptimizationStatus 404 | * @return CampaignConfig 405 | */ 406 | public function setAdServingOptimizationStatus($adServingOptimizationStatus) { 407 | $this->adServingOptimizationStatus = $adServingOptimizationStatus; 408 | return $this; 409 | } 410 | 411 | /** 412 | * Get the name of the campaign. 413 | * @return mixed 414 | */ 415 | public function getCampaignName() { 416 | return $this->campaignName; 417 | } 418 | 419 | /** 420 | * Set the name of the campaign. 421 | * @param mixed $campaignName 422 | * @return CampaignConfig 423 | */ 424 | public function setCampaignName($campaignName) { 425 | $this->campaignName = $campaignName; 426 | return $this; 427 | } 428 | 429 | /** 430 | * Get the serving status of the campaign. 431 | * @return string 432 | */ 433 | public function getServingStatus() { 434 | return $this->servingStatus; 435 | } 436 | 437 | /** 438 | * Set the serving status of the campaign. 439 | * @param $servingStatus 440 | * @return $this 441 | */ 442 | public function setServingStatus($servingStatus) { 443 | $this->servingStatus = $servingStatus; 444 | return $this; 445 | } 446 | 447 | /** 448 | * Get the ID of the campaign. 449 | * @return mixed 450 | */ 451 | public function getCampaignId() { 452 | return $this->campaignId; 453 | } 454 | 455 | /** 456 | * Set the ID of the campaign. 457 | * @param mixed $campaignId 458 | * @return CampaignConfig 459 | */ 460 | public function setCampaignId($campaignId) { 461 | $this->campaignId = $campaignId; 462 | return $this; 463 | } 464 | 465 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![EasyAdWordsLogo](https://i.imgsafe.org/0e5e9af5e5.png) 2 | 3 | EasyAdWords is an easy-to-use and customizable library that simplifies the basic usage cases of the AdWords API with PHP Client library v25.3 currently. It basically allows **simpler reporting process** with *downloading* and *parsing* the report, and also allows entity operations such as **getting**, **creating** and **removing** campaigns, ad groups and keywords. 4 | 5 | For example, an `Account Performance Report` can easily be downloaded and formatted like the following simple snippet: 6 | ```php 7 | $config = new ReportConfig([ 8 | "adwordsConfigPath" => 'my_adwords_config_file_path', 9 | "clientCustomerId" => 'my_client_customer_id', 10 | "refreshToken" => 'my_oauth_refresh_token', 11 | "fields" => ['Date', 'Clicks', 'Impressions'], 12 | "startDate" => '2017-01-22', 13 | "endDate" => '2017-01-25' 14 | ]); 15 | 16 | // The report object is initialized. 17 | $report = new AccountPerformanceReport($config); 18 | 19 | // Download the report and format it to a flat array. 20 | $report->download()->format(); 21 | 22 | // Access the report property of the object. 23 | $report->getReport(); 24 | ``` 25 | 26 | ## Table of Contents 27 | - [Installation](#installation) 28 | - [Auth](#auth) 29 | - [Config](#config) 30 | * [Required Fields](#required-fields) 31 | * [Optional Fields](#optional-fields) 32 | - [Reporting](#reporting) 33 | - [Entities](#entities) 34 | * [Account](#account) 35 | * [Campaign](#campaign) 36 | * [AdGroup](#adgroup) 37 | * [Keyword](#keyword) 38 | + [`Keyword`](#keyword) 39 | + [`KeywordBatch`](#keywordbatch) 40 | - [Contribution](#contribution) 41 | - [License](#license) 42 | 43 | 44 | ## Installation 45 | 46 | `composer require adprolabs/easy-adwords` 47 | 48 | ## Auth 49 | Most of the package is developed with the user is logged in via Google in mind. Therefore, there are some helpers for authentication process in EasyAdWords. First of all, you need client ID and client secret, instructions about that can be found [here with more details about the authentication process](https://developers.google.com/adwords/api/docs/guides/authentication#create_a_client_id_and_client_secret). After you created your client ID and secret, you can use them to create an oAuth object and then use it to register your user. 50 | 51 | Assume that you used this part in constructor, which means this is used for both redirecting and callback parts: 52 | 53 | ```php 54 | use EasyAdWords\AdWordsAuth\AdWordsAuth; 55 | use Google\AdsApi\AdWords\v201609\mcm\CustomerService; 56 | 57 | class MyAuth { 58 | 59 | public function __construct(){ 60 | 61 | // Parameters for the authentication process. 62 | $authorizationURI = "https://accounts.google.com/o/oauth2/v2/auth"; 63 | $redirectURI = "my_redirect_uri.com"; 64 | $clientId = "my_client_id"; 65 | $clientSecret = "my_client_secret"; 66 | $scopes = ['https://www.googleapis.com/auth/adwords']; 67 | 68 | // Create oAuth config array. 69 | $config = [ 70 | 'authorizationUri' => $authorizationURI, 71 | 'redirectUri' => $redirectURI, 72 | 'tokenCredentialUri' => CredentialsLoader::TOKEN_CREDENTIAL_URI, 73 | 'clientId' => $clientId, 74 | 'clientSecret' => $clientSecret, 75 | 'scope' => $scopes 76 | ]; 77 | 78 | // Create an auth object. 79 | $this->authObject = new AdWordsAuth(NULL, 'my_adwords_config_file_path'); 80 | 81 | // Get the oAuth object from the 82 | $this->oauth2 = $this->authObject->buildOAuthObject($this->config); 83 | } 84 | 85 | // These two are explained below. 86 | public function redirectToGoogle(); 87 | public function googleCallback(); 88 | } 89 | ``` 90 | 91 | This part is for redirection to the Google now: 92 | ```php 93 | public function redirectToGoogle(){ 94 | 95 | // Set the state for the request. 96 | $this->oauth2->setState(sha1(openssl_random_pseudo_bytes(1024))); 97 | $_SESSION['oauth2state'] = $oauth2->getState(); 98 | 99 | $accessConfig = ['access_type' => 'offline']; 100 | header('Location: ' . $oauth2->buildFullAuthorizationUri($accessConfig)); 101 | exit; 102 | } 103 | ``` 104 | 105 | After the user is redirected to the Google and allowed your application to access data, Google will redirect the user to your "redirectUri" address, which needs to be the callback. An example callback can be as follows: 106 | ```php 107 | public function googleCallback(){ 108 | 109 | // Check the state of the callback request. 110 | if (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])){ 111 | unset($_SESSION['oauth2state']); 112 | exit('Invalid state.'); 113 | } else { 114 | 115 | // Set the auth code and get the credentials. 116 | $this->oauth2->setCode($request->code); 117 | $credentials = $this->oauth2->fetchAuthToken(); 118 | 119 | // Build the oAuth session for service usage. 120 | $this->authObject->setOAuthCredentials($this->oauth2); 121 | $this->authObject->buildSession(); 122 | 123 | // Create the service and get the AdWords customers of the account. 124 | $customerService = $this->authObject->getAdWordsService(CustomerService::class); 125 | $customers = $customerService->getCustomers(); 126 | } 127 | } 128 | ``` 129 | 130 | 131 | This is it, now you have your access token and refresh token in the `$credentials` parameter and you downloaded the customers of the account, now you can do whatever you want. Note that, the `$this->authObject->buildOAuthObject($this->config);` line returns an instance of `Google\Auth\OAuth2` object, therefore you can use any methods of it with the object and also get help from the [AdWords API documentation](https://developers.google.com/adwords/api/docs/guides/start). 132 | 133 | ## Config 134 | Basically, EasyAdWords aims to create an easy-to-use interface between the developer and the *AdWords PHP Client library*. In order to keep this process simple, EasyAdWords uses configuration objects across different entities and operations. All of these config objects are specialized for the service they are used with; however, they all extend the base `Config` class. 135 | ### Required Fields 136 | The `Config` class contains the following fields as required, since they are required for every service used with EasyAdWords: 137 | 138 | - `adwordsConfigPath` => The path to the AdWords config file. If this is not given, the package looks for `adsapi_php.ini` file in the project root. 139 | - `clientCustomerId` => ID of the customer to operate on. **Required.** 140 | - `refreshToken` => Refresh token of the authenticated user. **Required.** 141 | - `fields` => Fields to get. **Required for get operations.** 142 | 143 | Keep in mind that these fields are **required** for all of the config objects, except that the `adwordsConfigPath` key, which seems to be not necessary, however if not given, the AdWords PHP Client library will look for the `adsapi_php.ini` file in the project root, therefore it is **required to have this file**. 144 | ### Optional Fields 145 | The following are optional values that can be used with any config object for entity operations. Note that reporting does allow pagination to be used, instead you need to filter your reports with appropriate predicates if the response was too large. 146 | 147 | - `paginated` => Boolean value to determine if the operation will be performed page by page, useful if you get `SizeLimitError.RESPONSE_SIZE_LIMIT_EXCEEDED` error with a `get` operation on an entity. 148 | - `pageSize` => Page size for the `get` operations, default is 10000, the maximum number allowed. 149 | 150 | ## Reporting 151 | EasyAdWords contains some basic classes that allows to get reports from AdWords easily. The following are available reporting classes for now: 152 | - `AccountPerformanceReport` 153 | - `AdGroupPerformanceReport` 154 | - `AdPerformanceReport` 155 | - `CampaignPerformanceReport` 156 | - `CustomReport` 157 | - `FinalUrlReport` 158 | - `KeywordsPerformanceReport` 159 | - `SearchQueryPerformanceReport` 160 | 161 | All of these classes implement the same *interface*, therefore they all have the same methods to use. Basically, all of these report classes need to construct the report objects with a `ReportConfig` instance. An example `ReportConfig` object is as follows: 162 | 163 | ```php 164 | use EasyAdwords\Reports\ReportConfig; 165 | 166 | $config = new ReportConfig([ 167 | "adwordsConfigPath" => 'my_adwords_config_file_path', 168 | "clientCustomerId" => 'my_client_customer_id', 169 | "refreshToken" => 'my_oauth_refresh_token', 170 | "fields" => ['Date', 'Clicks', 'Impressions'], 171 | "startDate" => '2017-01-22', 172 | "endDate" => '2017-01-25', 173 | "predicates" => [new Predicate('Clicks', PredicateOperator::GREATER_THAN, [10])] 174 | ]); 175 | ``` 176 | 177 | This `ReportConfig` object is constructed over a simple array. Available fields for the array are as follows: 178 | 179 | - `startDate` => Start date of the report. **Required.** 180 | - `endDate` => End date of the report. **Required.** 181 | - `predicates` => Predicates to filter the report. 182 | 183 | The report object can now be initialized with the newly created `ReportConfig` object. After creating the report instance, we can simply call `download()` and `format()` methods on the object in order to download the report as CSV and format it to a simple, one-dimensional array respectively. An example usage is as follows: 184 | 185 | ```php 186 | use EasyAdWords\Reports\AccountPerformanceReport; 187 | 188 | // The report object is initialized. 189 | $report = new AccountPerformanceReport($config); 190 | 191 | // Download the report and store it as a CSV string. 192 | $report->download(); 193 | 194 | // Format the report CSV into a flat array. 195 | $report->format(); 196 | 197 | // Access the report property of the object. 198 | $report->getReport(); 199 | ``` 200 | 201 | This process is same for all of the reports. In addition to the available report classes, one can simply create a **custom report** by using the `CustomReport` class with the same config objects and methods. The only difference is, using a custom report, there needs to be a parameter given to the `download()` method of the report object, indicating the type of the report. The parameter given must be a constant from the `ReportDefinitionReportType` class of the AdWords PHP Client library. An example report using the same config object above is as follows: 202 | 203 | ```php 204 | use EasyAdWords\Reports\CustomReport; 205 | 206 | $reportType = ReportDefinitionReportType::URL_PERFORMANCE_REPORT; 207 | 208 | // The custom report object is initialized. 209 | $report = new CustomReport($config, $reportType); 210 | 211 | // Download the URL Performance Report and store it as a CSV string. 212 | $report->download(); 213 | 214 | // Format the report CSV into a flat array. 215 | $report->format(); 216 | 217 | // Access the report property of the object. 218 | $report->getReport(); 219 | ``` 220 | 221 | Note that, after formatting the report, the CSV version of the report is not available. 222 | 223 | Available methods for reports are as follows: 224 | - `download()`: Downloads the report and stores it in the `report` property of the object. 225 | - `format()`: Formats the CSV report into a flat array. 226 | - `saveToFile($filePath)`: Saves the `report` property of the object to the given file. 227 | - `downloadToFile($filePath)`: Downloads and stores the report in the given file path. Note that this method does not keep the report in the report object after downloading and writing to the file. 228 | 229 | ## Entities 230 | EasyAdWords offers basic entity operations for campaigns, ad groups and keywords. Basically, all of these three entities are able to perform 3 basic operations: 231 | - `create` => Creates an instance of the entity in Google AdWords. 232 | - `get` => Gets the instances of the entity that fits specified criteria. 233 | - `remove` => Removes the instance of the entity from Google AdWords. 234 | 235 | **There is also an account entity, which only contains the `get` operation for now.** 236 | 237 | Basically, all of these entity objects operate with special config objects, just like the reporting objects. Therefore, an appropriate config object for the entity must be created, and then, the entity object can be constructed by using this config object. 238 | 239 | All the entity objects are extending the base class `Entity` and implementing the `EntityInterface`. Therefore, after every operation, result of the operation is accessible as a property of the entity object, called `operationResult`, which can be accessed by using the method `getOperationResult()`. 240 | 241 | Available entities are **Account**, **Campaign**, **Ad Group** and **Keyword** for now. All the entities have their corresponding config objects, such as `CampaignConfig`. 242 | 243 | The usage is same across the entity methods `create`, `get` and `remove`. As the nature of the `get` operation, the results can be filtered by specifying the `predicates` parameter, or can be ordered by `ordering` parameter. If there are no predicates set, all the instances of the entity will be listed. All the `get` operations will return an array of entity objects from Google AdWords PHP library, which can be used according to the Google AdWords API documentation. An example result is as follows for a `get` operation on `Account` entity: 244 | 245 | ```php 246 | $accountList = $account->get(); 247 | print_r($accountList); 248 | 249 | /* The result is as follows. 250 | Array 251 | ( 252 | [0] => Google\AdsApi\AdWords\v201609\mcm\ManagedCustomer Object 253 | ( 254 | [name:protected] => account_name 255 | [customerId:protected] => customer_id_of_account 256 | [canManageClients:protected] => 257 | [currencyCode:protected] => currency_code_of_account 258 | [dateTimeZone:protected] => date_time_zone_of_account 259 | [testAccount:protected] => 260 | [accountLabels:protected] => 261 | [excludeHiddenAccounts:protected] => 262 | ) 263 | ) 264 | */ 265 | 266 | // The fields can be accessed by appropriate getters. 267 | $accountList[0]->getName(); // account_name 268 | $accountList[0]->getCustomerId(); // customer_id_of_account 269 | 270 | ``` 271 | 272 | ### Account 273 | Account entity is the simplest entity in the package. It only contains a `get` method for the objects. The entity operates on an `AccountConfig` object, and this object must contain the `fields` parameter along with the required fields above, that determining the fields that will be returned from AdWords as the result. 274 | 275 | An example usage is as follows: 276 | 277 | ```php 278 | use EasyAdWords\Accounts\AccountConfig; 279 | use EasyAdWords\Accounts\Account; 280 | 281 | $fields = array('CustomerId', 'Name', 'CanManageClients'); 282 | 283 | // Create the account configuration object. 284 | $accountConfig = new AccountConfig([ 285 | "adwordsConfigPath" => 'my_adwords_config_file_path', 286 | "clientCustomerId" => 'my_client_customer_id', 287 | "refreshToken" => 'my_oauth_refresh_token', 288 | "fields" => $fields 289 | ]); 290 | 291 | // Create the campaign object with the config object. 292 | $account = new Account($accountConfig); 293 | 294 | // Get the account list from Google AdWords. 295 | $account->get(); 296 | ``` 297 | ### Campaign 298 | Like all the entities, the *Campaign* entity operates on a config object of the class `CampaignConfig`. The `CampaignConfig` class contains the following fields, in addition to the fields in the base `Config` class: 299 | 300 | ``` 301 | 'campaignId' => ID of the campaign. 302 | 'campaignName' => Name of the campaign. 303 | 'advertisingChannelType' => Advertising channel of the campaign. Default is 'SEARCH'. 304 | 'status' => Status of the campaign. Default is 'PAUSED'. 305 | 'budget' => Budget of the campaign, e.g. 50 means 50$. Default is 50. 306 | 'budgetName' => Name of the budget. 307 | 'biddingStrategyType' => Bidding strategy type of the campaign. Default is 'MANUAL_CPC'. 308 | 'budgetDeliveryMethod' => Budget delivery method of the campaign. Default is 'STANDARD'. 309 | 'targetGoogleSearch' => Target Google search if true. Default is true. 310 | 'targetSearchNetwork' => Target search network if true. Default is true. 311 | 'targetContentNetwork' => Target content network if true. Default is true. 312 | 'startDate' => Start date of the campaign. Default is today. 313 | 'endDate' => End date of the campaign. 314 | 'adServingOptimizationStatus' => Ad serving optimization status of the campaign. 315 | 'servingStatus' => Serving status of the campaign. Default is 'SERVING'. 316 | 'useDefaults' => Boolean value, allows to use defaults if true. 317 | ``` 318 | 319 | Not all these parameters are required for all of the campaign operations, some are needed for `create` operation, while some others are required for `remove` operation. However, if you do not provide some important properties, especially when creating a campaign, you will be facing with some errors. If you don't want to give every option for a campaign and use the defaults, just set `useDefaults` to `true`, and it will use the defaults. *Keep in mind that, when creating a campaign, EasyAdWords sets the campaign status to 'PAUSED' in order to not to spend money on a misconfigured campaign on default, if otherwise is not stated. Also, you still need to provide a campaign name even with the defaults.* 320 | 321 | A basic usage of the campaign entity is as follows: 322 | ```php 323 | use Google\AdsApi\AdWords\v201609\cm\AdvertisingChannelType; 324 | use Google\AdsApi\AdWords\v201609\cm\CampaignStatus; 325 | use Google\AdsApi\AdWords\v201609\cm\BudgetBudgetDeliveryMethod; 326 | use Google\AdsApi\AdWords\v201609\cm\BiddingStrategyType; 327 | use Google\AdsApi\AdWords\v201609\cm\ServingStatus; 328 | use EasyAdWords\Campaigns\CampaignConfig; 329 | use EasyAdWords\Campaigns\Campaign; 330 | 331 | // Create the campaign configuration object. 332 | $config = new CampaignConfig([ 333 | "adwordsConfigPath" => 'my_adwords_config_file_path', 334 | "clientCustomerId" => 'my_client_customer_id', 335 | "refreshToken" => 'my_oauth_refresh_token', 336 | "startDate" => '2017-06-22', 337 | "campaignName" => "EasyAdWords_TestCampaign_".uniqid(), 338 | "budget" => 100, 339 | "advertisingChannelType" => AdvertisingChannelType::SEARCH, 340 | "status" => CampaignStatus::PAUSED, 341 | "biddingStrategyType" => BiddingStrategyType::MANUAL_CPC, 342 | "budgetDeliveryMethod" => BudgetBudgetDeliveryMethod::STANDARD, 343 | "servingStatus" => ServingStatus::SERVING, 344 | "targetGoogleSearch" => true, 345 | "targetSearchNetwork" => true, 346 | "targetContentNetwork" => true, 347 | "startDate" => date('Ymd'), 348 | ]); 349 | 350 | // Create a new campaign configuration with 'useDefaults' option. 351 | $config = new CampaignConfig([ 352 | "adwordsConfigPath" => 'my_adwords_config_file_path', 353 | "clientCustomerId" => 'my_client_customer_id', 354 | "refreshToken" => 'my_oauth_refresh_token', 355 | "startDate" => '2017-06-22', 356 | "campaignName" => "EasyAdWords_TestCampaign_".uniqid(), 357 | "useDefaults" => true 358 | ]); 359 | 360 | // Create the campaign object with the config object. 361 | $campaign = new Campaign($config); 362 | 363 | // Create the campaign on Google AdWords. 364 | $campaign->create(); 365 | 366 | // Get the result of the campaign creation. 367 | $campaign->getOperationResult(); 368 | 369 | ``` 370 | 371 | ### AdGroup 372 | `AdGroup` entity is using the same simple set of methods and configuration logic. It works by using the `AdGroupConfig` object. The `AdGroupConfig` object consists of the following fields: 373 | 374 | ``` 375 | 'campaignId' => The campaign ID of the ad group. 376 | 'adGroupName' => The name of the ad group. 377 | 'adGroupId' => The ID of the ad group to operate on. 378 | 'status' => The status of the ad group, must be an AdGroupStatus instance. Default is 'PAUSED'. 379 | 'bid' => The bid amount to give the ad group, without extra zeros, e.g. 50 means 50$. 380 | ``` 381 | 382 | Some of these fields are required for some of the operations. For instance, `campaignId`, `adGroupName` and `bid` are required fields for creating an ad group. 383 | 384 | A basic usage of the `AdGroup` entity is as follows: 385 | ```php 386 | use EasyAdWords\AdGroups\AdGroup; 387 | use EasyAdWords\AdGroups\AdGroupConfig; 388 | 389 | // Create the ad group configuration object. 390 | $config = new AdGroupConfig([ 391 | "adwordsConfigPath" => 'my_adwords_config_file_path', 392 | "clientCustomerId" => 'my_client_customer_id', 393 | "refreshToken" => 'my_oauth_refresh_token', 394 | "campaignId" => 'my_campaign_id', 395 | "adGroupName" => 'EasyAdWords_AdGroup_TEST', 396 | "bid" => 25 397 | ]); 398 | 399 | // Create the ad group object with the config object. 400 | $adGroup = new AdGroup($config); 401 | 402 | // Create the ad group on Google AdWords. 403 | $adGroup->create(); 404 | 405 | // Get the result of the ad group creation. 406 | $adGroup->getOperationResult(); 407 | 408 | ``` 409 | 410 | ### Keyword 411 | Keyword entity is a candidate for both singular and batch operations. Therefore, there are 2 different classes for Keyword entities. One of them is `Keyword` entity, which is used just like the `Campaign` and `AdGroup` entities; same set of methods and the same initialization process with `KeywordConfig` object. However, this class is intended to be used for singular entity operations, and in the case of keywords, this is not very useful. There is a need for batch keyword operations and AdWords Client library allows multiple operations to be sent over the same single request. Therefore, the second class `KeywordBatch` is implemented for batch keyword addition operations. 412 | 413 | Both of these classes extend the same `KeywordBase` class. 414 | 415 | #### `Keyword` 416 | The `Keyword` class can be used with the same set of methods with other entities. It is initialized with the `KeywordConfig` object. The `KeywordConfig` object contains the following fields: 417 | ``` 418 | 'keyword' => Name of the keyword. 419 | 'keywordId' => ID of the keyword to operate on. 420 | 'matchType' => Match type of the keyword. 421 | 'finalUrls' => Array of the final URLs for the keyword. 422 | 'adGroupId' => ID of the ad group of the keyword. 423 | 'bid' => Bid of the keyword. 424 | 'status' => Status of the keyword. 425 | ``` 426 | 427 | The usage of the class is almost the same with the other entities: 428 | ```php 429 | use EasyAdWords\Keywords\Keyword; 430 | use EasyAdWords\Keywords\KeywordConfig 431 | 432 | // Create the keyword configuration object. 433 | $config = new KeywordConfig([ 434 | "adwordsConfigPath" => 'my_adwords_config_file_path', 435 | "clientCustomerId" => 'my_client_customer_id', 436 | "refreshToken" => 'my_oauth_refresh_token', 437 | "adGroupId" => 'my_ad_group_id', 438 | "keyword" => 'space invaders', 439 | "matchType" => KeywordMatchType::EXACT, 440 | "finalUrls" => 'http://example.com', 441 | "bid" => 25, 442 | "status" => UserStatus::ENABLED 443 | ]); 444 | 445 | // Create the keyword object with the config object. 446 | $keyword = new Keyword($config); 447 | 448 | // Create the keyword on Google AdWords. 449 | $keyword->create(); 450 | 451 | // Get the result of the keyword creation. 452 | $keyword->getOperationResult(); 453 | 454 | ``` 455 | 456 | #### `KeywordBatch` 457 | `KeywordBatch` class allows to create multiple keywords in the Google AdWords at once. The class is constructed over a simple `KeywordBatchConfig` object, which has only one additional value other than the required base values, `batchSize`. `batchSize` value determines how many of the keywords will be grouped into one request. The batch size can be at most 5000, however [the AdWords API documentation recommends passing at most 2000 operation per request](https://developers.google.com/adwords/api/docs/appendix/limits#general), therefore the default batch size is 2000 in `KeywordBatchConfig` objects. 458 | 459 | The `KeywordBatch` object is simply constructed over the config object. After creating the instance, the object is ready to get the list of keywords. For each keyword to create, you need to create a `KeywordConfig` object in order to define the properties of the keyword and append this config object to the `KeywordBatch` object. This way, **you can append as many keywords as you want** to the batch object, and it will process all of those objects by batches of size `batchSize`. *Note that the `KeywordConfig` objects to append a keyword do not need to contain the `adWordsConfigPath`, `clientCustomerId` and `refreshToken` parameters, as those were given in the `KeywordBatchConfig` object.* In order to complete the operation and create keywords on Google AdWords, you need to call the method `mutate()` on the `KeywordBatch` object. Until you call the `mutate()` method, all the keywords will be just an array inside the object. 460 | 461 | An example usage of `KeywordBatch` is as follows: 462 | ```php 463 | 464 | use EasyAdWords\Keywords\KeywordBatchConfig; 465 | use EasyAdWords\Keywords\KeywordBatch; 466 | 467 | // Keywords to add. 468 | $keywords = ['quick brown fox','jumps over','the lazy dog']; 469 | 470 | // Create the keyword batch configuration object. 471 | $config = new KeywordBatchConfig([ 472 | "adwordsConfigPath" => 'my_adwords_config_file_path', 473 | "clientCustomerId" => 'my_client_customer_id', 474 | "refreshToken" => 'my_oauth_refresh_token', 475 | "batchSize" => 500 476 | ]); 477 | 478 | // Create the keyword batch object with the config object. 479 | $keywordBatch = new KeywordBatch($config); 480 | 481 | // Loop over the keywords and append them to the batch object. 482 | foreach($keywords as $keyword) { 483 | $keywordConfig = new KeywordConfig([ 484 | "adGroupId" => 'my_ad_group_id', 485 | "keyword" => $keyword, 486 | "matchType" => KeywordMatchType::EXACT, 487 | "finalUrls" => 'http://example.com', 488 | "bid" => 25, 489 | "status" => UserStatus::ENABLED 490 | ]); 491 | 492 | $keywordBatch->append($keywordConfig); 493 | } 494 | 495 | // Apply the new keywords to the Google AdWords. 496 | $keywordBatch->mutate(); 497 | ``` 498 | 499 | With the batch config class, you can create keywords in batches, thus decrease the network requests for creating keywords. **The `KeywordBatch` class is only available for batch keyword addition operations for now.** 500 | 501 | ## Contribution 502 | **Your participation to EasyAdWords development in any form is very welcome!** In order to contribute on the package, you need to clone the project and include it using the `repositories` option in your `composer.json` file. An example usage is as follows: 503 | 504 | ```json 505 | "repositories": [{ 506 | "type": "vcs", 507 | "url": "path/to/easy-adwords" 508 | }], 509 | "require": { 510 | "adprolabs/easy-adwords": "dev-master" 511 | }, 512 | ``` 513 | 514 | Note that `repositories` is in the same level with `require` key, not nested inside something else. The `repositories` option works with the `vcs` value in `type`. Therefore, in order to test the package in another project with including it as a package like above, you need to commit your changes on the package and then `composer update` on the test project in order to get the latest changes you have made. 515 | 516 | After successfully updating the project with self-explanatory commit messages and adding comments to the code in PHPDoc style with proper explanations, you can submit a pull request with an explanation of why the update was required and what was your solution for this problem. 517 | 518 | Also, you can contribute to EasyAdWords by creating an issue with a well-defined and reproducable problem or giving feedback about the package and its design. **Any form of participation is very welcomed.** 519 | 520 | ## License 521 | EasyAdWords is released under the MIT Licence. For further information, see the [LICENSE.md](LICENSE.md). 522 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "c1323de17df7dcec03038b21a47132c8", 8 | "packages": [ 9 | { 10 | "name": "firebase/php-jwt", 11 | "version": "v5.0.0", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/firebase/php-jwt.git", 15 | "reference": "9984a4d3a32ae7673d6971ea00bae9d0a1abba0e" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/firebase/php-jwt/zipball/9984a4d3a32ae7673d6971ea00bae9d0a1abba0e", 20 | "reference": "9984a4d3a32ae7673d6971ea00bae9d0a1abba0e", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": ">=5.3.0" 25 | }, 26 | "require-dev": { 27 | "phpunit/phpunit": " 4.8.35" 28 | }, 29 | "type": "library", 30 | "autoload": { 31 | "psr-4": { 32 | "Firebase\\JWT\\": "src" 33 | } 34 | }, 35 | "notification-url": "https://packagist.org/downloads/", 36 | "license": [ 37 | "BSD-3-Clause" 38 | ], 39 | "authors": [ 40 | { 41 | "name": "Neuman Vong", 42 | "email": "neuman+pear@twilio.com", 43 | "role": "Developer" 44 | }, 45 | { 46 | "name": "Anant Narayanan", 47 | "email": "anant@php.net", 48 | "role": "Developer" 49 | } 50 | ], 51 | "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", 52 | "homepage": "https://github.com/firebase/php-jwt", 53 | "time": "2017-06-27T22:17:23+00:00" 54 | }, 55 | { 56 | "name": "google/auth", 57 | "version": "v1.3.0", 58 | "source": { 59 | "type": "git", 60 | "url": "https://github.com/google/google-auth-library-php.git", 61 | "reference": "8f7c96146b2c62d3f4c6bbc4b5bb8a8e396b0b71" 62 | }, 63 | "dist": { 64 | "type": "zip", 65 | "url": "https://api.github.com/repos/google/google-auth-library-php/zipball/8f7c96146b2c62d3f4c6bbc4b5bb8a8e396b0b71", 66 | "reference": "8f7c96146b2c62d3f4c6bbc4b5bb8a8e396b0b71", 67 | "shasum": "" 68 | }, 69 | "require": { 70 | "firebase/php-jwt": "~2.0|~3.0|~4.0|~5.0", 71 | "guzzlehttp/guzzle": "~5.3.1|~6.0", 72 | "guzzlehttp/psr7": "^1.2", 73 | "php": ">=5.4", 74 | "psr/cache": "^1.0", 75 | "psr/http-message": "^1.0" 76 | }, 77 | "require-dev": { 78 | "friendsofphp/php-cs-fixer": "^1.11", 79 | "guzzlehttp/promises": "0.1.1|^1.3", 80 | "phpunit/phpunit": "^4.8.36|^5.7", 81 | "sebastian/comparator": ">=1.2.3" 82 | }, 83 | "type": "library", 84 | "autoload": { 85 | "psr-4": { 86 | "Google\\Auth\\": "src" 87 | } 88 | }, 89 | "notification-url": "https://packagist.org/downloads/", 90 | "license": [ 91 | "Apache-2.0" 92 | ], 93 | "description": "Google Auth Library for PHP", 94 | "homepage": "http://github.com/google/google-auth-library-php", 95 | "keywords": [ 96 | "Authentication", 97 | "google", 98 | "oauth2" 99 | ], 100 | "time": "2018-04-06T19:26:30+00:00" 101 | }, 102 | { 103 | "name": "googleads/googleads-php-lib", 104 | "version": "34.0.0", 105 | "source": { 106 | "type": "git", 107 | "url": "https://github.com/googleads/googleads-php-lib.git", 108 | "reference": "7f086c308c3abd9198a64d70da7302085c73b19d" 109 | }, 110 | "dist": { 111 | "type": "zip", 112 | "url": "https://api.github.com/repos/googleads/googleads-php-lib/zipball/7f086c308c3abd9198a64d70da7302085c73b19d", 113 | "reference": "7f086c308c3abd9198a64d70da7302085c73b19d", 114 | "shasum": "" 115 | }, 116 | "require": { 117 | "ext-openssl": "*", 118 | "ext-soap": "*", 119 | "google/auth": "^1.0.0", 120 | "guzzlehttp/guzzle": "^6.0", 121 | "guzzlehttp/psr7": "^1.2", 122 | "monolog/monolog": "^1.17.1", 123 | "php": ">=5.5.9", 124 | "phpdocumentor/reflection-docblock": "^4.0.0 || ^3.0.3", 125 | "symfony/serializer": "^2.8.0 || ^3.0.3 || ^4.0.0" 126 | }, 127 | "require-dev": { 128 | "php": ">=5.5.17", 129 | "phpunit/phpunit": "^4.8.35 || ^5.7", 130 | "squizlabs/php_codesniffer": "^2.9 || ^3.2" 131 | }, 132 | "suggest": { 133 | "php-64bit": ">=5.5.9" 134 | }, 135 | "type": "library", 136 | "autoload": { 137 | "psr-4": { 138 | "Google\\AdsApi\\": "src/Google/AdsApi/" 139 | } 140 | }, 141 | "notification-url": "https://packagist.org/downloads/", 142 | "license": [ 143 | "Apache-2.0" 144 | ], 145 | "authors": [ 146 | { 147 | "name": "Google", 148 | "homepage": "https://github.com/googleads/googleads-php-lib/contributors" 149 | } 150 | ], 151 | "description": "Google Ads APIs Client Library for PHP (AdWords and DFP)", 152 | "homepage": "https://github.com/googleads/googleads-php-lib", 153 | "time": "2018-03-28T06:13:06+00:00" 154 | }, 155 | { 156 | "name": "guzzlehttp/guzzle", 157 | "version": "dev-master", 158 | "source": { 159 | "type": "git", 160 | "url": "https://github.com/guzzle/guzzle.git", 161 | "reference": "73bf0937061461ca45292a93aa3b7e9010f2e753" 162 | }, 163 | "dist": { 164 | "type": "zip", 165 | "url": "https://api.github.com/repos/guzzle/guzzle/zipball/73bf0937061461ca45292a93aa3b7e9010f2e753", 166 | "reference": "73bf0937061461ca45292a93aa3b7e9010f2e753", 167 | "shasum": "" 168 | }, 169 | "require": { 170 | "guzzlehttp/promises": "^1.0", 171 | "guzzlehttp/psr7": "^1.4", 172 | "php": ">=5.5" 173 | }, 174 | "require-dev": { 175 | "ext-curl": "*", 176 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", 177 | "psr/log": "^1.0" 178 | }, 179 | "suggest": { 180 | "psr/log": "Required for using the Log middleware" 181 | }, 182 | "type": "library", 183 | "extra": { 184 | "branch-alias": { 185 | "dev-master": "6.3-dev" 186 | } 187 | }, 188 | "autoload": { 189 | "files": [ 190 | "src/functions_include.php" 191 | ], 192 | "psr-4": { 193 | "GuzzleHttp\\": "src/" 194 | } 195 | }, 196 | "notification-url": "https://packagist.org/downloads/", 197 | "license": [ 198 | "MIT" 199 | ], 200 | "authors": [ 201 | { 202 | "name": "Michael Dowling", 203 | "email": "mtdowling@gmail.com", 204 | "homepage": "https://github.com/mtdowling" 205 | } 206 | ], 207 | "description": "Guzzle is a PHP HTTP client library", 208 | "homepage": "http://guzzlephp.org/", 209 | "keywords": [ 210 | "client", 211 | "curl", 212 | "framework", 213 | "http", 214 | "http client", 215 | "rest", 216 | "web service" 217 | ], 218 | "time": "2018-04-09 20:04:58" 219 | }, 220 | { 221 | "name": "guzzlehttp/promises", 222 | "version": "dev-master", 223 | "source": { 224 | "type": "git", 225 | "url": "https://github.com/guzzle/promises.git", 226 | "reference": "136531aa4e42f9b1971a47fb0faf60da00d2fefa" 227 | }, 228 | "dist": { 229 | "type": "zip", 230 | "url": "https://api.github.com/repos/guzzle/promises/zipball/136531aa4e42f9b1971a47fb0faf60da00d2fefa", 231 | "reference": "136531aa4e42f9b1971a47fb0faf60da00d2fefa", 232 | "shasum": "" 233 | }, 234 | "require": { 235 | "php": ">=5.5.0" 236 | }, 237 | "require-dev": { 238 | "phpunit/phpunit": "^4.8.36" 239 | }, 240 | "type": "library", 241 | "extra": { 242 | "branch-alias": { 243 | "dev-master": "1.4-dev" 244 | } 245 | }, 246 | "autoload": { 247 | "psr-4": { 248 | "GuzzleHttp\\Promise\\": "src/" 249 | }, 250 | "files": [ 251 | "src/functions_include.php" 252 | ] 253 | }, 254 | "notification-url": "https://packagist.org/downloads/", 255 | "license": [ 256 | "MIT" 257 | ], 258 | "authors": [ 259 | { 260 | "name": "Michael Dowling", 261 | "email": "mtdowling@gmail.com", 262 | "homepage": "https://github.com/mtdowling" 263 | } 264 | ], 265 | "description": "Guzzle promises library", 266 | "keywords": [ 267 | "promise" 268 | ], 269 | "time": "2018-03-25 01:26:01" 270 | }, 271 | { 272 | "name": "guzzlehttp/psr7", 273 | "version": "dev-master", 274 | "source": { 275 | "type": "git", 276 | "url": "https://github.com/guzzle/psr7.git", 277 | "reference": "6858c3f0e94b96c114c28f9185f295bf30a53e58" 278 | }, 279 | "dist": { 280 | "type": "zip", 281 | "url": "https://api.github.com/repos/guzzle/psr7/zipball/6858c3f0e94b96c114c28f9185f295bf30a53e58", 282 | "reference": "6858c3f0e94b96c114c28f9185f295bf30a53e58", 283 | "shasum": "" 284 | }, 285 | "require": { 286 | "php": ">=5.4.0", 287 | "psr/http-message": "~1.0" 288 | }, 289 | "provide": { 290 | "psr/http-message-implementation": "1.0" 291 | }, 292 | "require-dev": { 293 | "phpunit/phpunit": "~4.0" 294 | }, 295 | "type": "library", 296 | "extra": { 297 | "branch-alias": { 298 | "dev-master": "1.4-dev" 299 | } 300 | }, 301 | "autoload": { 302 | "psr-4": { 303 | "GuzzleHttp\\Psr7\\": "src/" 304 | }, 305 | "files": [ 306 | "src/functions_include.php" 307 | ] 308 | }, 309 | "notification-url": "https://packagist.org/downloads/", 310 | "license": [ 311 | "MIT" 312 | ], 313 | "authors": [ 314 | { 315 | "name": "Michael Dowling", 316 | "email": "mtdowling@gmail.com", 317 | "homepage": "https://github.com/mtdowling" 318 | }, 319 | { 320 | "name": "Tobias Schultze", 321 | "homepage": "https://github.com/Tobion" 322 | } 323 | ], 324 | "description": "PSR-7 message implementation that also provides common utility methods", 325 | "keywords": [ 326 | "http", 327 | "message", 328 | "request", 329 | "response", 330 | "stream", 331 | "uri", 332 | "url" 333 | ], 334 | "time": "2018-04-11 19:14:35" 335 | }, 336 | { 337 | "name": "monolog/monolog", 338 | "version": "1.x-dev", 339 | "source": { 340 | "type": "git", 341 | "url": "https://github.com/Seldaek/monolog.git", 342 | "reference": "fd8c787753b3a2ad11bc60c063cff1358a32a3b4" 343 | }, 344 | "dist": { 345 | "type": "zip", 346 | "url": "https://api.github.com/repos/Seldaek/monolog/zipball/fd8c787753b3a2ad11bc60c063cff1358a32a3b4", 347 | "reference": "fd8c787753b3a2ad11bc60c063cff1358a32a3b4", 348 | "shasum": "" 349 | }, 350 | "require": { 351 | "php": ">=5.3.0", 352 | "psr/log": "~1.0" 353 | }, 354 | "provide": { 355 | "psr/log-implementation": "1.0.0" 356 | }, 357 | "require-dev": { 358 | "aws/aws-sdk-php": "^2.4.9 || ^3.0", 359 | "doctrine/couchdb": "~1.0@dev", 360 | "graylog2/gelf-php": "~1.0", 361 | "jakub-onderka/php-parallel-lint": "0.9", 362 | "php-amqplib/php-amqplib": "~2.4", 363 | "php-console/php-console": "^3.1.3", 364 | "phpunit/phpunit": "~4.5", 365 | "phpunit/phpunit-mock-objects": "2.3.0", 366 | "ruflin/elastica": ">=0.90 <3.0", 367 | "sentry/sentry": "^0.13", 368 | "swiftmailer/swiftmailer": "^5.3|^6.0" 369 | }, 370 | "suggest": { 371 | "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", 372 | "doctrine/couchdb": "Allow sending log messages to a CouchDB server", 373 | "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", 374 | "ext-mongo": "Allow sending log messages to a MongoDB server", 375 | "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", 376 | "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", 377 | "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", 378 | "php-console/php-console": "Allow sending log messages to Google Chrome", 379 | "rollbar/rollbar": "Allow sending log messages to Rollbar", 380 | "ruflin/elastica": "Allow sending log messages to an Elastic Search server", 381 | "sentry/sentry": "Allow sending log messages to a Sentry server" 382 | }, 383 | "type": "library", 384 | "extra": { 385 | "branch-alias": { 386 | "dev-master": "2.0.x-dev" 387 | } 388 | }, 389 | "autoload": { 390 | "psr-4": { 391 | "Monolog\\": "src/Monolog" 392 | } 393 | }, 394 | "notification-url": "https://packagist.org/downloads/", 395 | "license": [ 396 | "MIT" 397 | ], 398 | "authors": [ 399 | { 400 | "name": "Jordi Boggiano", 401 | "email": "j.boggiano@seld.be", 402 | "homepage": "http://seld.be" 403 | } 404 | ], 405 | "description": "Sends your logs to files, sockets, inboxes, databases and various web services", 406 | "homepage": "http://github.com/Seldaek/monolog", 407 | "keywords": [ 408 | "log", 409 | "logging", 410 | "psr-3" 411 | ], 412 | "time": "2017-06-19 01:22:40" 413 | }, 414 | { 415 | "name": "phpdocumentor/reflection-common", 416 | "version": "dev-master", 417 | "source": { 418 | "type": "git", 419 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git", 420 | "reference": "81339187a96c6fdb70cd876b129891f8ca501508" 421 | }, 422 | "dist": { 423 | "type": "zip", 424 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/81339187a96c6fdb70cd876b129891f8ca501508", 425 | "reference": "81339187a96c6fdb70cd876b129891f8ca501508", 426 | "shasum": "" 427 | }, 428 | "require": { 429 | "php": ">=7.1" 430 | }, 431 | "require-dev": { 432 | "phpunit/phpunit": "^6" 433 | }, 434 | "type": "library", 435 | "extra": { 436 | "branch-alias": { 437 | "dev-master": "2.x-dev" 438 | } 439 | }, 440 | "autoload": { 441 | "psr-4": { 442 | "phpDocumentor\\Reflection\\": [ 443 | "src" 444 | ] 445 | } 446 | }, 447 | "notification-url": "https://packagist.org/downloads/", 448 | "license": [ 449 | "MIT" 450 | ], 451 | "authors": [ 452 | { 453 | "name": "Jaap van Otterdijk", 454 | "email": "opensource@ijaap.nl" 455 | } 456 | ], 457 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure", 458 | "homepage": "http://www.phpdoc.org", 459 | "keywords": [ 460 | "FQSEN", 461 | "phpDocumentor", 462 | "phpdoc", 463 | "reflection", 464 | "static analysis" 465 | ], 466 | "time": "2018-02-14 18:58:54" 467 | }, 468 | { 469 | "name": "phpdocumentor/reflection-docblock", 470 | "version": "dev-master", 471 | "source": { 472 | "type": "git", 473 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 474 | "reference": "182609736818dc750d42470c0be2a5ed74bad3bd" 475 | }, 476 | "dist": { 477 | "type": "zip", 478 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/182609736818dc750d42470c0be2a5ed74bad3bd", 479 | "reference": "182609736818dc750d42470c0be2a5ed74bad3bd", 480 | "shasum": "" 481 | }, 482 | "require": { 483 | "php": ">=7.1", 484 | "phpdocumentor/type-resolver": "^0", 485 | "webmozart/assert": "^1" 486 | }, 487 | "require-dev": { 488 | "doctrine/instantiator": "^1", 489 | "mockery/mockery": "^1" 490 | }, 491 | "type": "library", 492 | "extra": { 493 | "branch-alias": { 494 | "dev-master": "4.x-dev" 495 | } 496 | }, 497 | "autoload": { 498 | "psr-4": { 499 | "phpDocumentor\\Reflection\\": "src" 500 | } 501 | }, 502 | "notification-url": "https://packagist.org/downloads/", 503 | "license": [ 504 | "MIT" 505 | ], 506 | "authors": [ 507 | { 508 | "name": "Mike van Riel", 509 | "email": "me@mikevanriel.com" 510 | } 511 | ], 512 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", 513 | "time": "2018-02-14 19:00:58" 514 | }, 515 | { 516 | "name": "phpdocumentor/type-resolver", 517 | "version": "dev-master", 518 | "source": { 519 | "type": "git", 520 | "url": "https://github.com/phpDocumentor/TypeResolver.git", 521 | "reference": "69bf1b199584f2004365a150c2e6cfbe852b6d66" 522 | }, 523 | "dist": { 524 | "type": "zip", 525 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/69bf1b199584f2004365a150c2e6cfbe852b6d66", 526 | "reference": "69bf1b199584f2004365a150c2e6cfbe852b6d66", 527 | "shasum": "" 528 | }, 529 | "require": { 530 | "php": ">=7.1", 531 | "phpdocumentor/reflection-common": "^2" 532 | }, 533 | "require-dev": { 534 | "mockery/mockery": "^1.0", 535 | "phpunit/phpunit": "^6.5" 536 | }, 537 | "type": "library", 538 | "extra": { 539 | "branch-alias": { 540 | "dev-master": "0.x-dev" 541 | } 542 | }, 543 | "autoload": { 544 | "psr-4": { 545 | "phpDocumentor\\Reflection\\": "src" 546 | } 547 | }, 548 | "notification-url": "https://packagist.org/downloads/", 549 | "license": [ 550 | "MIT" 551 | ], 552 | "authors": [ 553 | { 554 | "name": "Mike van Riel", 555 | "email": "me@mikevanriel.com" 556 | } 557 | ], 558 | "time": "2018-02-14 18:59:20" 559 | }, 560 | { 561 | "name": "psr/cache", 562 | "version": "dev-master", 563 | "source": { 564 | "type": "git", 565 | "url": "https://github.com/php-fig/cache.git", 566 | "reference": "78c5a01ddbf11cf731f1338a4f5aba23b14d5b47" 567 | }, 568 | "dist": { 569 | "type": "zip", 570 | "url": "https://api.github.com/repos/php-fig/cache/zipball/78c5a01ddbf11cf731f1338a4f5aba23b14d5b47", 571 | "reference": "78c5a01ddbf11cf731f1338a4f5aba23b14d5b47", 572 | "shasum": "" 573 | }, 574 | "require": { 575 | "php": ">=5.3.0" 576 | }, 577 | "type": "library", 578 | "extra": { 579 | "branch-alias": { 580 | "dev-master": "1.0.x-dev" 581 | } 582 | }, 583 | "autoload": { 584 | "psr-4": { 585 | "Psr\\Cache\\": "src/" 586 | } 587 | }, 588 | "notification-url": "https://packagist.org/downloads/", 589 | "license": [ 590 | "MIT" 591 | ], 592 | "authors": [ 593 | { 594 | "name": "PHP-FIG", 595 | "homepage": "http://www.php-fig.org/" 596 | } 597 | ], 598 | "description": "Common interface for caching libraries", 599 | "keywords": [ 600 | "cache", 601 | "psr", 602 | "psr-6" 603 | ], 604 | "time": "2016-10-13 14:48:10" 605 | }, 606 | { 607 | "name": "psr/http-message", 608 | "version": "dev-master", 609 | "source": { 610 | "type": "git", 611 | "url": "https://github.com/php-fig/http-message.git", 612 | "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" 613 | }, 614 | "dist": { 615 | "type": "zip", 616 | "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", 617 | "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", 618 | "shasum": "" 619 | }, 620 | "require": { 621 | "php": ">=5.3.0" 622 | }, 623 | "type": "library", 624 | "extra": { 625 | "branch-alias": { 626 | "dev-master": "1.0.x-dev" 627 | } 628 | }, 629 | "autoload": { 630 | "psr-4": { 631 | "Psr\\Http\\Message\\": "src/" 632 | } 633 | }, 634 | "notification-url": "https://packagist.org/downloads/", 635 | "license": [ 636 | "MIT" 637 | ], 638 | "authors": [ 639 | { 640 | "name": "PHP-FIG", 641 | "homepage": "http://www.php-fig.org/" 642 | } 643 | ], 644 | "description": "Common interface for HTTP messages", 645 | "homepage": "https://github.com/php-fig/http-message", 646 | "keywords": [ 647 | "http", 648 | "http-message", 649 | "psr", 650 | "psr-7", 651 | "request", 652 | "response" 653 | ], 654 | "time": "2016-08-06 14:39:51" 655 | }, 656 | { 657 | "name": "psr/log", 658 | "version": "dev-master", 659 | "source": { 660 | "type": "git", 661 | "url": "https://github.com/php-fig/log.git", 662 | "reference": "3490ba5925e6dcbe6de950c5c6b8dce9f6e96eda" 663 | }, 664 | "dist": { 665 | "type": "zip", 666 | "url": "https://api.github.com/repos/php-fig/log/zipball/3490ba5925e6dcbe6de950c5c6b8dce9f6e96eda", 667 | "reference": "3490ba5925e6dcbe6de950c5c6b8dce9f6e96eda", 668 | "shasum": "" 669 | }, 670 | "require": { 671 | "php": ">=5.3.0" 672 | }, 673 | "type": "library", 674 | "extra": { 675 | "branch-alias": { 676 | "dev-master": "1.0.x-dev" 677 | } 678 | }, 679 | "autoload": { 680 | "psr-4": { 681 | "Psr\\Log\\": "Psr/Log/" 682 | } 683 | }, 684 | "notification-url": "https://packagist.org/downloads/", 685 | "license": [ 686 | "MIT" 687 | ], 688 | "authors": [ 689 | { 690 | "name": "PHP-FIG", 691 | "homepage": "http://www.php-fig.org/" 692 | } 693 | ], 694 | "description": "Common interface for logging libraries", 695 | "homepage": "https://github.com/php-fig/log", 696 | "keywords": [ 697 | "log", 698 | "psr", 699 | "psr-3" 700 | ], 701 | "time": "2018-04-03 15:59:15" 702 | }, 703 | { 704 | "name": "symfony/serializer", 705 | "version": "dev-master", 706 | "source": { 707 | "type": "git", 708 | "url": "https://github.com/symfony/serializer.git", 709 | "reference": "acb8164bfe1c69bf61bad81603c36ad3497d6f6f" 710 | }, 711 | "dist": { 712 | "type": "zip", 713 | "url": "https://api.github.com/repos/symfony/serializer/zipball/acb8164bfe1c69bf61bad81603c36ad3497d6f6f", 714 | "reference": "acb8164bfe1c69bf61bad81603c36ad3497d6f6f", 715 | "shasum": "" 716 | }, 717 | "require": { 718 | "php": "^7.1.3" 719 | }, 720 | "conflict": { 721 | "phpdocumentor/type-resolver": "<0.2.1", 722 | "symfony/dependency-injection": "<3.4", 723 | "symfony/property-access": "<3.4", 724 | "symfony/property-info": "<3.4", 725 | "symfony/yaml": "<3.4" 726 | }, 727 | "require-dev": { 728 | "doctrine/annotations": "~1.0", 729 | "doctrine/cache": "~1.0", 730 | "phpdocumentor/reflection-docblock": "^3.0|^4.0", 731 | "symfony/cache": "~3.4|~4.0", 732 | "symfony/config": "~3.4|~4.0", 733 | "symfony/dependency-injection": "~3.4|~4.0", 734 | "symfony/http-foundation": "~3.4|~4.0", 735 | "symfony/property-access": "~3.4|~4.0", 736 | "symfony/property-info": "~3.4|~4.0", 737 | "symfony/validator": "~3.4|~4.0", 738 | "symfony/yaml": "~3.4|~4.0" 739 | }, 740 | "suggest": { 741 | "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.", 742 | "doctrine/cache": "For using the default cached annotation reader and metadata cache.", 743 | "psr/cache-implementation": "For using the metadata cache.", 744 | "symfony/config": "For using the XML mapping loader.", 745 | "symfony/http-foundation": "To use the DataUriNormalizer.", 746 | "symfony/property-access": "For using the ObjectNormalizer.", 747 | "symfony/property-info": "To deserialize relations.", 748 | "symfony/yaml": "For using the default YAML mapping loader." 749 | }, 750 | "type": "library", 751 | "extra": { 752 | "branch-alias": { 753 | "dev-master": "4.1-dev" 754 | } 755 | }, 756 | "autoload": { 757 | "psr-4": { 758 | "Symfony\\Component\\Serializer\\": "" 759 | }, 760 | "exclude-from-classmap": [ 761 | "/Tests/" 762 | ] 763 | }, 764 | "notification-url": "https://packagist.org/downloads/", 765 | "license": [ 766 | "MIT" 767 | ], 768 | "authors": [ 769 | { 770 | "name": "Fabien Potencier", 771 | "email": "fabien@symfony.com" 772 | }, 773 | { 774 | "name": "Symfony Community", 775 | "homepage": "https://symfony.com/contributors" 776 | } 777 | ], 778 | "description": "Symfony Serializer Component", 779 | "homepage": "https://symfony.com", 780 | "time": "2018-03-30 15:58:13" 781 | }, 782 | { 783 | "name": "webmozart/assert", 784 | "version": "dev-master", 785 | "source": { 786 | "type": "git", 787 | "url": "https://github.com/webmozart/assert.git", 788 | "reference": "0df1908962e7a3071564e857d86874dad1ef204a" 789 | }, 790 | "dist": { 791 | "type": "zip", 792 | "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a", 793 | "reference": "0df1908962e7a3071564e857d86874dad1ef204a", 794 | "shasum": "" 795 | }, 796 | "require": { 797 | "php": "^5.3.3 || ^7.0" 798 | }, 799 | "require-dev": { 800 | "phpunit/phpunit": "^4.6", 801 | "sebastian/version": "^1.0.1" 802 | }, 803 | "type": "library", 804 | "extra": { 805 | "branch-alias": { 806 | "dev-master": "1.3-dev" 807 | } 808 | }, 809 | "autoload": { 810 | "psr-4": { 811 | "Webmozart\\Assert\\": "src/" 812 | } 813 | }, 814 | "notification-url": "https://packagist.org/downloads/", 815 | "license": [ 816 | "MIT" 817 | ], 818 | "authors": [ 819 | { 820 | "name": "Bernhard Schussek", 821 | "email": "bschussek@gmail.com" 822 | } 823 | ], 824 | "description": "Assertions to validate method input/output with nice error messages.", 825 | "keywords": [ 826 | "assert", 827 | "check", 828 | "validate" 829 | ], 830 | "time": "2018-01-29 19:49:41" 831 | } 832 | ], 833 | "packages-dev": [], 834 | "aliases": [], 835 | "minimum-stability": "dev", 836 | "stability-flags": [], 837 | "prefer-stable": false, 838 | "prefer-lowest": false, 839 | "platform": [], 840 | "platform-dev": [] 841 | } 842 | --------------------------------------------------------------------------------