Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -732,3 +732,27 @@ Questions and issues: [fopost.com/contact](https://fopost.com/contact) or the [i
## License

MIT. Copyright Porter Bridge, LLC.

### Google Ads

Campaigns, ad groups, ads, audiences and insights are on `$client->ads()` and dispatch by
connection. What only Google has is under `$client->ads()->google()`:

```php
$keywords = $client->ads()->google()->keywords('c4d5e6f7-…', '1234567890');

$client->ads()->google()->createKeyword(
workspaceId: '7d2b8c11-…',
connectionId: 'c4d5e6f7-…',
customerId: '1234567890',
adGroupId: '1234567890~adGroup~77',
text: 'running shoes',
matchType: 'EXACT',
);
```

Also `keywordIdeas()`, `keywordMetrics()`, `searchTerms()`, `bidStrategies()`,
`adSchedule()` and `setAdSchedule()`, the negative keyword lists, `assets()` and
`assetGroups()`, `localServicesLeads()`, the conversion methods, and `query()` for a raw
read-only GAQL SELECT. Changes need the `publish` scope as well as `ads`; the customer id
has to name an account the connection's grant reaches.
34 changes: 34 additions & 0 deletions src/Model/GoogleAdScheduleSlot.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace Fopost\Sdk\Model;

/** One slot of a campaign's ad schedule. */
final class GoogleAdScheduleSlot extends Model
{
private function __construct(
array $raw,
public readonly string $id,
public readonly string $dayOfWeek,
public readonly ?int $startHour,
public readonly ?int $endHour,
public readonly ?float $bidModifier,
) {
parent::__construct($raw);
}

public static function fromArray(mixed $data): static
{
$data = is_array($data) ? $data : [];

return new self(
$data,
self::requiredStr($data, 'id'),
self::requiredStr($data, 'dayOfWeek'),
self::int($data, 'startHour'),
self::int($data, 'endHour'),
is_numeric(self::field($data, 'bidModifier')) ? (float) self::field($data, 'bidModifier') : null,
);
}
}
34 changes: 34 additions & 0 deletions src/Model/GoogleAsset.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace Fopost\Sdk\Model;

/** A sitelink, callout or structured snippet. */
final class GoogleAsset extends Model
{
private function __construct(
array $raw,
public readonly string $id,
public readonly ?string $name,
public readonly string $type,
public readonly ?string $text,
public readonly ?string $finalUrl,
) {
parent::__construct($raw);
}

public static function fromArray(mixed $data): static
{
$data = is_array($data) ? $data : [];

return new self(
$data,
self::requiredStr($data, 'id'),
self::str($data, 'name'),
self::requiredStr($data, 'type'),
self::str($data, 'text'),
self::str($data, 'finalUrl'),
);
}
}
35 changes: 35 additions & 0 deletions src/Model/GoogleAssetGroup.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace Fopost\Sdk\Model;

/** A Performance Max asset group. */
final class GoogleAssetGroup extends Model
{
private function __construct(
array $raw,
public readonly string $id,
public readonly string $campaignId,
public readonly string $name,
public readonly string $status,
/** @var array<int, string> */
public readonly array $finalUrls,
) {
parent::__construct($raw);
}

public static function fromArray(mixed $data): static
{
$data = is_array($data) ? $data : [];

return new self(
$data,
self::requiredStr($data, 'id'),
self::requiredStr($data, 'campaignId'),
self::requiredStr($data, 'name'),
self::requiredStr($data, 'status'),
array_values(array_filter(self::seq($data, 'finalUrls'), 'is_string')),
);
}
}
36 changes: 36 additions & 0 deletions src/Model/GoogleAssetLink.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace Fopost\Sdk\Model;

/** Where an asset is attached; an asset with no links serves nowhere. */
final class GoogleAssetLink extends Model
{
private function __construct(
array $raw,
public readonly string $id,
public readonly string $assetId,
public readonly string $level,
public readonly ?string $ownerId,
public readonly string $fieldType,
public readonly string $status,
) {
parent::__construct($raw);
}

public static function fromArray(mixed $data): static
{
$data = is_array($data) ? $data : [];

return new self(
$data,
self::requiredStr($data, 'id'),
self::requiredStr($data, 'assetId'),
self::requiredStr($data, 'level'),
self::str($data, 'ownerId'),
self::requiredStr($data, 'fieldType'),
self::requiredStr($data, 'status'),
);
}
}
32 changes: 32 additions & 0 deletions src/Model/GoogleAssetsResult.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace Fopost\Sdk\Model;

/** The account's assets, with the links that put each one under an ad. */
final class GoogleAssetsResult extends Model
{
/**
* @param array<int, GoogleAsset> $assets
* @param array<int, GoogleAssetLink> $links
*/
private function __construct(
array $raw,
public readonly array $assets,
public readonly array $links,
) {
parent::__construct($raw);
}

public static function fromArray(mixed $data): static
{
$data = is_array($data) ? $data : [];

return new self(
$data,
GoogleAsset::listFrom(self::seq($data, 'assets')),
GoogleAssetLink::listFrom(self::seq($data, 'links')),
);
}
}
34 changes: 34 additions & 0 deletions src/Model/GoogleBidStrategy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace Fopost\Sdk\Model;

/** A portfolio bid strategy on the account. */
final class GoogleBidStrategy extends Model
{
private function __construct(
array $raw,
public readonly string $id,
public readonly string $name,
public readonly string $type,
public readonly string $status,
public readonly ?int $campaignCount,
) {
parent::__construct($raw);
}

public static function fromArray(mixed $data): static
{
$data = is_array($data) ? $data : [];

return new self(
$data,
self::requiredStr($data, 'id'),
self::requiredStr($data, 'name'),
self::requiredStr($data, 'type'),
self::requiredStr($data, 'status'),
self::int($data, 'campaignCount'),
);
}
}
38 changes: 38 additions & 0 deletions src/Model/GoogleConversionAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace Fopost\Sdk\Model;

/** A conversion action on the account. */
final class GoogleConversionAction extends Model
{
private function __construct(
array $raw,
public readonly string $id,
public readonly string $name,
public readonly string $category,
public readonly string $status,
public readonly string $type,
public readonly ?string $countingType,
public readonly ?int $valueMinor,
) {
parent::__construct($raw);
}

public static function fromArray(mixed $data): static
{
$data = is_array($data) ? $data : [];

return new self(
$data,
self::requiredStr($data, 'id'),
self::requiredStr($data, 'name'),
self::requiredStr($data, 'category'),
self::requiredStr($data, 'status'),
self::requiredStr($data, 'type'),
self::str($data, 'countingType'),
self::int($data, 'valueMinor'),
);
}
}
38 changes: 38 additions & 0 deletions src/Model/GoogleKeyword.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace Fopost\Sdk\Model;

/** A keyword on an ad group. `id` is `<customerId>~keyword~<adGroupId>~<criterionId>`. */
final class GoogleKeyword extends Model
{
private function __construct(
array $raw,
public readonly string $id,
public readonly string $adGroupId,
public readonly string $text,
public readonly string $matchType,
public readonly string $status,
public readonly ?int $cpcBidMinor,
public readonly ?bool $negative,
) {
parent::__construct($raw);
}

public static function fromArray(mixed $data): static
{
$data = is_array($data) ? $data : [];

return new self(
$data,
self::requiredStr($data, 'id'),
self::requiredStr($data, 'adGroupId'),
self::requiredStr($data, 'text'),
self::requiredStr($data, 'matchType'),
self::requiredStr($data, 'status'),
self::int($data, 'cpcBidMinor'),
self::bool($data, 'negative'),
);
}
}
34 changes: 34 additions & 0 deletions src/Model/GoogleKeywordIdea.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace Fopost\Sdk\Model;

/** A keyword idea or its historical metrics. */
final class GoogleKeywordIdea extends Model
{
private function __construct(
array $raw,
public readonly string $text,
public readonly ?int $avgMonthlySearches,
public readonly ?string $competition,
public readonly ?int $lowTopOfPageBidMinor,
public readonly ?int $highTopOfPageBidMinor,
) {
parent::__construct($raw);
}

public static function fromArray(mixed $data): static
{
$data = is_array($data) ? $data : [];

return new self(
$data,
self::requiredStr($data, 'text'),
self::int($data, 'avgMonthlySearches'),
self::str($data, 'competition'),
self::int($data, 'lowTopOfPageBidMinor'),
self::int($data, 'highTopOfPageBidMinor'),
);
}
}
42 changes: 42 additions & 0 deletions src/Model/GoogleLocalServicesLead.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

namespace Fopost\Sdk\Model;

/** A lead from Local Services Ads, read live and never stored. */
final class GoogleLocalServicesLead extends Model
{
private function __construct(
array $raw,
public readonly string $id,
public readonly ?string $category,
public readonly ?string $service,
public readonly ?string $contactName,
public readonly ?string $phone,
public readonly ?string $email,
public readonly ?string $status,
public readonly ?string $type,
public readonly ?string $createdAt,
) {
parent::__construct($raw);
}

public static function fromArray(mixed $data): static
{
$data = is_array($data) ? $data : [];

return new self(
$data,
self::requiredStr($data, 'id'),
self::str($data, 'category'),
self::str($data, 'service'),
self::str($data, 'contactName'),
self::str($data, 'phone'),
self::str($data, 'email'),
self::str($data, 'status'),
self::str($data, 'type'),
self::str($data, 'createdAt'),
);
}
}
Loading
Loading