(int) ($dash['clicks'] ?? 0), 'impressions' => (int) ($dash['impressions'] ?? 0), 'position' => (float) ($dash['position'] ?? 0.0), ]; } $has_previous = (int) ($previous['clicks'] ?? 0) > 0 || (int) ($previous['impressions'] ?? 0) > 0; return [ 'clicks' => (int) ($current['clicks'] ?? 0), 'impressions' => (int) ($current['impressions'] ?? 0), 'position' => round((float) ($current['position'] ?? 0.0), 1), 'prev_clicks' => $has_previous ? (int) ($previous['clicks'] ?? 0) : null, 'prev_impressions' => $has_previous ? (int) ($previous['impressions'] ?? 0) : null, 'prev_position' => $has_previous ? round((float) ($previous['position'] ?? 0.0), 1) : null, 'period_days' => (int) ($context['frequency_days'] ?? 30), 'period_label' => (string) ($context['period_label'] ?? ''), ]; } /** * Zero clicks and zero impressions is a connected property with no * traffic — a placeholder, not a report. */ public function has_data(array $payload): bool { return (int) ($payload['clicks'] ?? 0) > 0 || (int) ($payload['impressions'] ?? 0) > 0; } public function render(array $payload): string { $days = (int) ($payload['period_days'] ?? 30); $ctr = self::ctr($payload['clicks'], $payload['impressions']); $clicks_change = ''; $imps_change = ''; $ctr_change = ''; $pos_change = ''; $compared = ''; if ($payload['prev_clicks'] !== null) { $c = Email_Report_Html::pct_change((float) $payload['clicks'], (float) $payload['prev_clicks']); $i = Email_Report_Html::pct_change((float) $payload['impressions'], (float) $payload['prev_impressions']); $clicks_change = $c ? Email_Report_Html::change($c['text'], $c['direction'], $c['direction'] !== 'down') : ''; $imps_change = $i ? Email_Report_Html::change($i['text'], $i['direction'], $i['direction'] !== 'down') : ''; $prev_ctr = self::ctr((int) $payload['prev_clicks'], (int) $payload['prev_impressions']); $pts = round(($ctr - $prev_ctr) * 100, 1); if (abs($pts) >= 0.1) { $ctr_change = Email_Report_Html::change( number_format_i18n(abs($pts), 1), $pts > 0 ? 'up' : 'down', $pts > 0, __('pts', 'thinkrank') ); } elseif ($prev_ctr > 0) { $ctr_change = Email_Report_Html::change('0', 'flat', true); } if ((float) $payload['prev_position'] > 0 && (float) $payload['position'] > 0) { $diff = round((float) $payload['prev_position'] - (float) $payload['position'], 1); if (abs($diff) >= 0.1) { // A smaller position number is better, so "up" here means improved. $pos_change = Email_Report_Html::change( number_format_i18n(abs($diff), 1), $diff > 0 ? 'up' : 'down', $diff > 0, $diff > 0 ? __('better', 'thinkrank') : __('worse', 'thinkrank') ); } else { $pos_change = Email_Report_Html::change('0', 'flat', true); } } $compared = ' · ' . sprintf( /* translators: %d: number of days in the comparison window. */ _n('compared with the previous %d day', 'compared with the previous %d days', $days, 'thinkrank'), $days ); } $eyebrow = '