I want to set my site logo programmatically, so that I can change the logo based on URL args.

I am able to set the $variables['logo_img']['#uri'] with the following code in MYTHEME.theme but still the logo displayed does not change.

I have cleared registry.

I have tried setting my own logo and using default logo settings in theme settings UI:

function THEME_preprocess_page(&$variables) {
  $variables['logo_img']['#uri'] = 'http://newlogo.jpg'; }

I have also tried this:

function THEME_preprocess_page(&$variables) {
  global $base_url, $base_path;
  $variables['logo'] = $base_url . $base_path . drupal_get_path('theme','THEME') . '/images/logos/newlogo.svg';

Any help?

2 Answers 2


How to change the site logo in .theme preprocess function?

The site logo is no longer in the page template. You can change it now in the branding block:

function mytheme_preprocess_block(&$variables) {
  if ($variables['base_plugin_id'] == 'system_branding_block') {
    $variables['site_logo'] = '/newlogo.jpg';


You mentioned you want to change the logo based on URL args. This would be difficult to do this in the system branding block, because the template is not rendering the render array, but transferring only the content of three variables and so any attempt to add cache meta data would be useless.

You have two options. Implement your own site logo block plugin in a module or use this theming only solution:

  • disable the site logo in the branding block
  • set a variable with the url for the logo in page preprocess $variables['logo']
  • add your own markup to the page twig to output the site logo


<a href="{{ path('<front>') }}" title="{{ 'Home'|t }}">
   <img src="{{ logo }}" alt="{{ 'Home'|t }}" />

By doing this in the page template you avoid caching problems because the page is already cached for each url separately.

  • Thank you very much for your detailed answer! I think what I want to do is "set a variable with the url for the logo in page preprocess", which I think is what I was aiming at in my first code example. Do you have pointers for this?
    – petergus
    Feb 5, 2017 at 18:32
  • Use the second code example from your question and then put the markup I've added to the answer in the page twig.
    – 4uk4
    Feb 5, 2017 at 18:43

If you need caching, you can do it with a pre_render callback from hook_block_view_system_branding_block_alter(), in which you set $build['content']['site_logo']['#uri'] and add cache metadata. This overrides the logo in the system branding block and preserves caching.

below is an excerpt from Drupal's color module where they use exactly this method.

You probably want something like this for caching:


You can define your logo's path in $build['content']['site_logo']['#uri'].

Full code:

 * Implements hook_block_view_BASE_BLOCK_ID_alter().
function color_block_view_system_branding_block_alter(array &$build, BlockPluginInterface $block) {
  $build['#pre_render'][] = 'color_block_view_pre_render';

 * #pre_render callback: Sets color preset logo.
function color_block_view_pre_render(array $build) {
  $theme_key = \Drupal::theme()->getActiveTheme()->getName();
  $config = \Drupal::config('color.theme.' . $theme_key);

  // Override logo.
  $logo = $config->get('logo');
  if ($logo && $build['content']['site_logo'] && preg_match('!' . $theme_key . '/logo.svg$!', $build['content']['site_logo']['#uri'])) {
    $build['content']['site_logo']['#uri'] = file_url_transform_relative(file_create_url($logo));

  return $build;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.