env('ADSENSE_CLIENT_ID'), 'client_secret' => env('ADSENSE_CLIENT_SECRET'), 'redirect_uri' => env( 'ADSENSE_REDIRECT_URI', rtrim((string) env('APP_URL', 'http://localhost'), '/').'/admin/adsense/oauth/callback' ), 'scope' => 'https://www.googleapis.com/auth/adsense.readonly', 'sync_enabled' => filter_var(env('ADSENSE_SYNC_ENABLED', true), FILTER_VALIDATE_BOOLEAN), 'api_base' => env('ADSENSE_API_BASE', 'https://adsense.googleapis.com/v2'), 'oauth_authorize_url' => env('ADSENSE_OAUTH_AUTHORIZE_URL', 'https://accounts.google.com/o/oauth2/v2/auth'), 'oauth_token_url' => env('ADSENSE_OAUTH_TOKEN_URL', 'https://oauth2.googleapis.com/token'), 'oauth_revoke_url' => env('ADSENSE_OAUTH_REVOKE_URL', 'https://oauth2.googleapis.com/revoke'), 'timeout' => max(5, (int) env('ADSENSE_HTTP_TIMEOUT', 20)), 'connect_timeout' => max(1, (int) env('ADSENSE_HTTP_CONNECT_TIMEOUT', 5)), 'retry_times' => max(1, (int) env('ADSENSE_HTTP_RETRY_TIMES', 3)), 'retry_sleep_ms' => max(0, (int) env('ADSENSE_HTTP_RETRY_SLEEP_MS', 400)), 'access_token_cache_prefix' => 'adsense.access_token.', 'access_token_skew_seconds' => 60, // Ad clients whose productCode is set to something else (YouTube host, video, search) // are skipped. Empty productCode still syncs unless the resource name is excluded. 'inventory_product_codes' => ['AFC'], 'inventory_excluded_client_prefixes' => [ 'ca-yt-host-', ], 'metrics' => [ 'ESTIMATED_EARNINGS', 'PAGE_VIEWS', 'PAGE_VIEWS_CTR', 'PAGE_VIEWS_RPM', 'AD_REQUESTS', 'AD_REQUESTS_COVERAGE', 'AD_REQUESTS_CTR', 'AD_REQUESTS_RPM', 'MATCHED_AD_REQUESTS', 'IMPRESSIONS', 'IMPRESSIONS_CTR', 'IMPRESSIONS_RPM', 'CLICKS', 'COST_PER_CLICK', ], 'recommended_placement_names' => [ 'Skinbase_Artwork_BeforeComments', 'Skinbase_Home_AfterTrending', 'Skinbase_Home_AfterFresh', 'Skinbase_Browse_InFeed', 'Skinbase_Search_InFeed', 'Skinbase_News_InArticle', ], ];