This project is a sample implementation for sending Google AdSense revenue reports via email, built with laravel-console-starter
- Automated AdSense Reporting: Fetches month-to-date revenue data from Google AdSense API
- Email Notifications: Sends formatted reports with total metrics, daily averages, and recent 7-day breakdown
- Scheduled Execution: Runs automatically every 3 hours via GitHub Actions
- Configurable Metrics: Easy customization of reported AdSense metrics
- Comprehensive Testing: Full test coverage with mocked API integration
- Framework: Laravel 12.0 (Console Application)
- Language: PHP 8.4
- API Integration: Google AdSense Management API
- Authentication: OAuth 2.0 with automatic token refresh
- Email: Laravel Mail with Amazon SES
- Testing: PHPUnit with Mockery
- Code Quality: Laravel Pint (PSR-12)
- CI/CD: GitHub Actions
-
AdSenseCommand (
app/Console/Commands/AdSenseCommand.php
)- Main Artisan command that orchestrates the reporting process
- Handles dependency injection and coordinates the workflow
-
AdSenseReport (
app/AdSenseReport.php
)- Service class for Google AdSense API integration
- Manages OAuth authentication and token refresh
- Converts API responses to usable array format
-
AdSenseReportTransformer (
app/AdSenseReportTransformer.php
)- Transforms raw AdSense API data into notification-ready format
- Handles data aggregation, metric calculations, and change analysis
- Separates data transformation concerns from notification delivery
-
AdSenseNotification (
app/Notifications/AdSenseNotification.php
)- Handles email formatting and delivery
- Generates Japanese/English reports with appropriate templates
- Focuses solely on notification presentation and delivery
config/ads.php
: AdSense API credentials and metric definitionsconfig/google.php
: Google OAuth configurationconfig/mail.php
: Email delivery settings
AdSenseCommand β AdSenseReport β Google AdSense API
β β
β Raw API Data (totals, averages, rows)
β β
β AdSenseReportTransformer
β β
β Notification Data (keyMetrics, totalMetrics, etc.)
β β
ββββββ AdSenseNotification β Email Report β User
Comprehensive test suite with 100% core functionality coverage:
# Run all tests
composer test
# Run specific test suite
php artisan test tests/Unit/AdSenseNotificationTest.php
# Code formatting
vendor/bin/pint
Test Coverage:
- Command execution and notification sending
- Email content formatting and metric calculation
- API integration with mocked Google services
- Configuration management and error handling
# Clone and install dependencies
composer install
# Copy environment file
cp .env.example .env
# Generate application key
php artisan key:generate
# Configure your AdSense API credentials (see OAuth setup below)
# Edit .env file with your Google credentials
# Run the report command
php artisan ads:report
# Run tests
composer test
Required environment variables in .env
:
# Google OAuth Credentials
GOOGLE_CLIENT_ID=your_client_id
GOOGLE_CLIENT_SECRET=your_client_secret
GOOGLE_REDIRECT=http://localhost/
# AdSense API Tokens
ADS_ACCESS_TOKEN=your_access_token
ADS_REFRESH_TOKEN=your_refresh_token
# Email Configuration (Amazon SES)
MAIL_MAILER=ses
[email protected]
MAIL_FROM_NAME="AdSense Reports"
[email protected]
MAIL_TO_NAME="Report Recipient"
# AWS SES Credentials
AWS_ACCESS_KEY_ID=your_aws_key
AWS_SECRET_ACCESS_KEY=your_aws_secret
AWS_DEFAULT_REGION=us-east-1
Customize reported metrics in config/ads.php
:
'metrics' => [
'PAGE_VIEWS', // Page views
'CLICKS', // Clicks
'COST_PER_CLICK', // Cost per click
'ESTIMATED_EARNINGS', // Estimated earnings
// 'AD_REQUESTS', // Ad requests
// 'AD_REQUESTS_CTR', // Click-through rate
// 'PAGE_RPM', // RPM
],
This guide walks you through the complete process to get AdSense Management API access and refresh tokens without running a web server.
Since this project is a console application that runs without a web interface, traditional OAuth authentication flows cannot be used. The AdSense API requires at least one-time user authorization to access account data, and service accounts are not supported for AdSense API access.
The solution is to:
- One-time authorization: Authenticate once to obtain a refresh token
- Long-term access: Use the refresh token to automatically obtain new access tokens indefinitely
- No web server needed: While you could set up a web server for OAuth flow,
oauth2l
provides a simpler command-line approach
Once you have the refresh token, your console application can run completely autonomously, refreshing access tokens as needed without any user interaction.
You'll create a Google Cloud project, configure OAuth, use oauth2l
to authorize, and store the credentials in a .env
file.
- Go to Google Cloud Console.
- Click the project dropdown in the top bar β "New Project".
- Name your project and click Create.
- In the Cloud Console, navigate to APIs & Services > Library.
- Search for "AdSense Management API".
- Click on it, then click "Enable".
- Go to APIs & Services > OAuth consent screen.
- Choose "External" for user type, then click Create.
- Fill in required app information:
- App name, support email
- Developer contact email
- Under Scopes, click "Add or Remove Scopes" and include:
https://www.googleapis.com/auth/adsense.readonly
- Under Test Users, add your Google account email.
- Save and continue to publish the consent screen.
- Go to APIs & Services > Credentials.
- Click "Create Credentials" > "OAuth Client ID".
- Choose "Desktop app" for Application Type.
- Name it and click Create.
- Download the client credentials JSON file (e.g.,
client_secret_XXX.json
) and save it securely.
You can install oauth2l
from the official GitHub repository:
https://github.com/google/oauth2l
Run the following command in your terminal:
oauth2l fetch \
--scope https://www.googleapis.com/auth/adsense.readonly \
--credentials ./client_secret_XXX.json \
--output_format json
This will launch a browser asking you to authorize access with your Google account. After successful login and consent, a JSON response like below will appear:
{
"access_token": "...access-token...",
"expiry": "2025-06-22T11:51:37.242796+09:00",
"refresh_token": "...refresh-token...",
"scope": "https://www.googleapis.com/auth/adsense.readonly",
"token_type": "Bearer"
}
Copy the access and refresh tokens into a .env
file:
GOOGLE_CLIENT_ID=client_id_from_json
GOOGLE_CLIENT_SECRET=client_secret_from_json
GOOGLE_REDIRECT=http://localhost/
ADS_ACCESS_TOKEN=...access-token...
ADS_REFRESH_TOKEN=...refresh-token...
These tokens can now be used by your application or script to make authorized requests to the AdSense API. The access token will expire, but you can use the refresh token to get a new one programmatically.
GOOGLE_REDIRECT
can be anything, so set it as you like.
- Security: Never commit
client_secret_XXX.json
or.env
files to version control. - Token Refreshing: You can use
oauth2l fetch
again or implement automatic refresh logic using the refresh token. - Scope Adjustments: If you need to change scopes, update the OAuth consent screen and reauthorize.
You now have full access to the AdSense API with long-term credentials, without needing to run a web server. Use the stored tokens to authenticate your scripts or apps easily.
MIT License