Analyzing Share of Voice

Measuring brand strength amongst an audience

Measuring the strength of a brand against competitor brands is a staple analysis for any brand monitoring solution. Share of voice use cases fit well with PYLON features.

note icon

When describing this pattern we'll refer to the example automotive recording which is available in the analysis sandbox. This recording captures audiences discussing three car brands and uses CSDL similar to the interaction filter shown in step 1 of the solution.


Typically for share of voice use cases you'll consider a number of the following aspects:

  • the share of voice for a set of brands
  • the share of audience for a set of brands
  • how share of voice varies over time
  • how type of engagement varies by brand
  • how share of voice varies by demographic and location

In this guide we'll take a look at each of the above scenarios, starting with analyzing overall share of voice, but also drilling down to share of voice amongst sections of an audience.

For example we'll see how you can analyze share of voice amongst demographic groups:

brand-demographic-breakdown

And by location:

brand-by-state-map

In this guide we'll walk through how you can perform share of voice analysis with Facebook topic data.

When is this pattern applicable?

Share of voice analysis is a common form of analysis typically used for brand monitoring (or brand health) and market research scenarios.

You can use share of voice analysis to:

  • see how a brand is performing in comparison to competitors
  • see which demographic groups interact with which brands
  • see how interaction with brands varies by location
  • see how interaction with brands varies over time

Share of voice analysis is typically carried out for brands, but you could apply exactly the same techniques to compare share of voice for other categories such as products and celebrities.

Solution

To take a closer look at share of voice analysis we'll step through how this analysis can be performed for the automotive example you're no doubt familiar with by now.

Step 1: Defining an audience to record

Naturally the first step in the process is to record data for the audience we'd like to analyze.

We can use the same interaction filter as used for the sandbox automotive recording. To keep things simple we'll additionally restrict our example to the US audience only:

( 
    fb.parent.content contains_any "Ford, BMW, Honda" 
    OR 
    fb.content contains_any "Ford, BMW, Honda" 
) 
AND 
( 
    fb.topics.category in "Cars, Automotive" 
    OR 
    fb.parent.topics.category in "Cars, Automotive" 
) 
AND 
( 
    fb.author.country_code in "US" 
)

Here we filter to automotive conversations (by specifying car/automotive topics), which mention at least one of the three brands, and additionally filter to only authors who are in the US.

Step 2: Adding tagging rules for your brands

Now that we have our filter defined we will use tags to classify the interactions that will be recorded by brand.

Tags are extremely useful for such use cases. Tags help you surface and organize recorded interactions into custom topics, such as brands & products which you can then reference in your analysis requests.

Tags are written using the following syntax:

tag top_namespace.next_namespace."[tag name]" { // CSDL conditions to match interactions }

Interactions that are matched by your interaction filter conditions are run through your tagging rules. If an interaction matches a tag rule then the tag is applied to the interaction before it is stored in your index.

In this case we want to add tags for each of our three brands. These can be written as follows:

tag.automotive.brand "Ford" { fb.parent.content contains_any "Ford" or fb.content contains_any "Ford" } 
tag.automotive.brand "BMW" { fb.parent.content contains_any "BMW" or fb.content contains_any "BMW" } 
tag.automotive.brand "Honda" { fb.parent.content contains_any "Honda" or fb.content contains_any "Honda" }

These are simple illustrative tags that look for keywords in the content of stories being posted and stories being engaged with. The CSDL clause for a tag rule can be as complex as you wish.

To add these tagging rules to our interaction filter we firstly enclose the filter statement in a return clause then add the tag rules above:

tag.automotive.brand "Ford" { fb.parent.content contains_any "Ford" or fb.content contains_any "Ford" } 
tag.automotive.brand "BMW" { fb.parent.content contains_any "BMW" or fb.content contains_any "BMW" } 
tag.automotive.brand "Honda" { fb.parent.content contains_any "Honda" or fb.content contains_any "Honda" } 

return { 
  ( 
    fb.parent.content contains_any "Ford, BMW, Honda" 
    OR 
    fb.content contains_any "Ford, BMW, Honda" 
  ) 
  AND 
  ( 
    fb.topics.category in "Cars, Automotive" 
    OR 
    fb.parent.topics.category in "Cars, Automotive" 
  ) 
  AND 
  ( 
    fb.author.country_code in "US" 
  ) 
}

Now that we have the interaction filter fully defined we can compile the CSDL and start a recording.

If a user now posts the following story...

Picked up my brand new BMW 3 series today - I love it!

The story will be recorded and tagged with "BMW". Of course we could add additional tagging rules to tag the products being discussed to give us more analysis options if we wish.

Note that if the following story is posted…

I can't decide between a Honda Jazz and Ford Fiesta - help please!

It will be recorded into the index tagged with both "Honda" and "Ford". All tags that match the interaction are applied.

Step 3: Analyzing overall share of voice

After running our example filter for a few hours we will have an index containing interactions (stories and engagements) that will have been tagged with the appropriate brands.

We can use our tags in our analysis to perform straight forward share of voice and share of audience analysis.

For example, using the DataSift Python client library we can analyze the count of interactions and unique authors for each brand:

# Start and end times for analysis
start = 1452729600
end = 1453939200

client = Client("DataSift username", "Identity API key")

analyze_parameters = {
  "analysis_type": "freqDist",
  "parameters": {
    "target": "interaction.tag_tree.automotive.brand",
    "threshold": 3
  }
}

result = client.pylon.analyze('index id', analyze_parameters, start=start, end=end)

Notice that the analysis target we are using here begins with 'interaction.tag_tree.' and then includes the namespace of our tags 'automotive.brand'.

The resulting data might look like so:

overall-share-of-voice

From the results we can plot two pie charts:

share-of-voice-pie-charts

The chart on the left shows share of voice for each brand by plotting the count of interactions for each. The chart on the right shows share of audience for each brand by plotting the count of unique authors for each.

Step 4: Using query filters to drill deeper

Query filters allow us to drill deeper into our index by segmenting the recorded interactions prior to analysis.

For example, if you use the following CSDL for your query filter on an analysis query:

interaction.tag_tree.automotive.brand == "BMW"

Only interactions that are tagged with "BMW" will be included in the analysis.

We can use query filters to look at how share of voice varies over time for our brands. To do so we can submit time series analysis queries to the index, one for each brand by making use of query filters, and plotting the results on one chart.

To carry out the analysis we could write the following code:

analyze_parameters = {
    'analysis_type': 'timeSeries',
    'parameters':
    {
        'span': 1,
        'interval': 'hour'
    }
}

timeseries_Ford = client.pylon.analyze('index id', analyze_parameters, start=start, end=end, 
    filter='interaction.tag_tree.automotive.brand == "Ford"')

timeseries_BMW = client.pylon.analyze('index id', analyze_parameters, start=start, end=end, 
    filter='interaction.tag_tree.automotive.brand == "BMW"')

timeseries_Honda = client.pylon.analyze('index id', analyze_parameters, start=start, end=end, 
    filter='interaction.tag_tree.automotive.brand == "Honda"')

Again each analysis result returns counts for both interactions and unique authors in each time slot allowing you to chart both share of voice and share of audience over time.

For example plotting share of voice gives the following result:

share-of-voice-timeseries

We can use the same principal to look at different aspects of our audience, for example investigating how users are engaging with each brand by the type of content they are posting.

To perform this analysis we can use the fb.media_type target, running a frequency distribution analysis for each brand:

analyze_parameters = {
  "analysis_type": "freqDist",
  "parameters": {
    "target": "fb.media_type",
    "threshold": 5
  }
}

mediatype_Ford = client.pylon.analyze('index id', analyze_parameters, start=start, end=end, 
    filter='interaction.tag_tree.automotive.brand == "Ford"')

mediatype_BMW = client.pylon.analyze('index id', analyze_parameters, start=start, end=end, 
    filter='interaction.tag_tree.automotive.brand == "BMW"')

mediatype_Honda = client.pylon.analyze('index id', analyze_parameters, start=start, end=end, 
    filter='interaction.tag_tree.automotive.brand == "Honda"')

Charting the results gives us the following:

brand-by-media-type

You can see that people engage relatively more with BMW by posting photos.

Step 5: Using tags with nested queries

We can also make use of our tags with nested queries.

For instance if we wanted to analyze share of voice by US state:

analyze_parameters = {
  "analysis_type": "freqDist",
  "parameters": {
    "target": "fb.author.region",
    "threshold": 50
  }, 
  "child": {
    "analysis_type": "freqDist",
      "parameters": {
        "target": "interaction.tag_tree.automotive.brand",
        "threshold": 3
    }
  }
}

by_state = client.pylon.analyze('index id', analyze_parameters, start=start, end=end)

Here we use fb.author.region as the top-level analysis target because it has a high cardinality and use our tags for child analysis.

We can present results on a map plotting the number of interactions per brand in each state. In this case the size of the pie chart reflects the total number of interactions for the state, and we use a colour for each brand.

brand-by-state-map

We can use the same principle to analyze share of voice by demographic group, in this case using a 3-level nested query.

analyze_parameters = {
  "analysis_type": "freqDist",
  "parameters": {
    "target": "interaction.tag_tree.automotive.brand",
    "threshold": 3
  }, 
  "child": {
    "analysis_type": "freqDist",
      "parameters": {
        "target": "fb.author.gender",
        "threshold": 2
    },
    "child": {
      "analysis_type": "freqDist",
        "parameters": {
          "target": "fb.author.age",
          "threshold": 6
      }
    }  
  }
}

by_demographic = client.pylon.analyze('index id', analyze_parameters, start=start, end=end)

In this case we use our tags as the top-level target, then use the fb.author.gender and fb.author.age targets in the child analysis.

Plotting the results gives the following charts:

brand-demographic-breakdown

As you can see, by simply adding a tag rule for each brand we give ourselves a wide range of analysis options.

Considerations

When performing share of voice analysis keep in mind:

  • You could choose to use topics in your tag rules to identify brands. Be aware that not all brands are present in the topic graph and some brands have multiple distinct topics.
  • As with any recording it is important to check you include your entire audience and try to remove as much noise as possible. Consider using super public posts to validate your interaction filter and tagging rules.
  • Use query filters to segment your audience. We have only included a small number of examples in this guide but the wide range of available targets gives you many options.
  • Share of voice will vary significantly across different locations. Make sure you consider analyzing share of voice by country and region.
  • Make sure that when you submit analysis queries for each brand you are comparing the same time period and are using the same query filters (if applicable) so your results are comparable.

Resources

For further reading, take a look at the following resources:

You may also find it useful to test your analysis queries with the example automotive recording referenced in this pattern. Contact your sales representative or account manager for access to the 'analysis sandbox'.