count * - daily: Y-m-d => count * - monthly: Y-m => count * - pages: landing path => (event name => count) * - seen: event name => count from every channel, used to check that the * configured events exist in the property at all * * The browser sorts events into the site's conversion groups, so renaming a * group never invalidates cached data. */ final class ConversionReport extends Report { /** * {@inheritDoc} * * @return string */ public function id() { return 'conversions'; } /** * {@inheritDoc} * * @return string */ public function section() { return Profile::SECTION_CONVERSIONS; } /** * {@inheritDoc} * * @return string[] */ public function segment_types() { return array( Segments::TYPE_PAGE ); } /** * {@inheritDoc} * * @return array */ public function args() { return array( 'kind' => array( 'type' => 'string', 'enum' => array( 'totals', 'daily', 'monthly', 'pages', 'seen' ), 'required' => true, ), ); } /** * {@inheritDoc} * * @param Profile $site Site. * @param array $params Parameters. * @return mixed */ public function run( Profile $site, array $params ) { $events = $site->all_conversion_events(); if ( ! $events ) { $this->segment( $site, $params ); return new \stdClass(); } $ga = $this->google->for_site( $site, Profile::SOURCE_ANALYTICS )->analytics(); $ttl = $this->ttl( $params['end'] ); $ranges = array( array( 'startDate' => $params['start'], 'endDate' => $params['end'], ), ); $metric = array( array( 'name' => 'eventCount' ) ); $segment = $this->segment( $site, $params ); $filter = Filters::all( Filters::organic( $site ), Filters::events( $events ), $segment ? SegmentFilter::ga( $segment ) : null ); switch ( $params['kind'] ) { case 'seen': // Any channel and no segment: "does this event exist?", not "how many organic?". $rows = $ga->run_report( $site->ga_property, array( 'dateRanges' => $ranges, 'dimensions' => array( array( 'name' => 'eventName' ) ), 'metrics' => $metric, 'dimensionFilter' => Filters::events( $events ), ), $ttl ); $out = array(); foreach ( $rows as $row ) { $out[ $row['d'][0] ] = (int) $row['m'][0]; } return self::map( $out ); case 'totals': $rows = $ga->run_report( $site->ga_property, array( 'dateRanges' => $ranges, 'dimensions' => array( array( 'name' => 'eventName' ) ), 'metrics' => $metric, 'dimensionFilter' => $filter, ), $ttl ); $out = array(); foreach ( $rows as $row ) { $out[ $row['d'][0] ] = (int) $row['m'][0]; } return self::map( $out ); case 'daily': case 'monthly': $daily = 'daily' === $params['kind']; $rows = $ga->run_report( $site->ga_property, array( 'dateRanges' => $ranges, 'dimensions' => array( array( 'name' => $daily ? 'date' : 'yearMonth' ) ), 'metrics' => $metric, 'dimensionFilter' => $filter, 'limit' => 1000, ), $ttl ); $out = array(); foreach ( $rows as $row ) { $v = $row['d'][0]; $key = substr( $v, 0, 4 ) . '-' . substr( $v, 4, 2 ) . ( $daily ? '-' . substr( $v, 6, 2 ) : '' ); $out[ $key ] = ( isset( $out[ $key ] ) ? $out[ $key ] : 0 ) + (int) $row['m'][0]; } return self::map( $out ); case 'pages': default: $rows = $ga->run_report( $site->ga_property, array( 'dateRanges' => $ranges, 'dimensions' => array( array( 'name' => 'landingPage' ), array( 'name' => 'eventName' ) ), 'metrics' => $metric, 'dimensionFilter' => $filter, 'limit' => 5000, ), $ttl ); $out = array(); foreach ( $rows as $row ) { $path = self::normalize_path( $row['d'][0] ); $event = $row['d'][1]; $out[ $path ][ $event ] = ( isset( $out[ $path ][ $event ] ) ? $out[ $path ][ $event ] : 0 ) + (int) $row['m'][0]; } return self::map( $out ); } } }