Warning: Table './devblogsdb/cache_page' is marked as crashed and last (automatic?) repair failed query: SELECT data, created, headers, expire, serialized FROM cache_page WHERE cid = 'http://www.softdevblogs.com/?q=aggregator/sources/29' in /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/database.mysql.inc on line 135

Warning: Cannot modify header information - headers already sent by (output started at /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/database.mysql.inc:135) in /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/bootstrap.inc on line 729

Warning: Cannot modify header information - headers already sent by (output started at /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/database.mysql.inc:135) in /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/bootstrap.inc on line 730

Warning: Cannot modify header information - headers already sent by (output started at /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/database.mysql.inc:135) in /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/bootstrap.inc on line 731

Warning: Cannot modify header information - headers already sent by (output started at /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/database.mysql.inc:135) in /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/bootstrap.inc on line 732
Software Development Blogs: Programming, Software Testing, Agile, Project Management
Skip to content

Software Development Blogs: Programming, Software Testing, Agile Project Management

Methods & Tools

Subscribe to Methods & Tools
if you are not afraid to read more than one page to be a smarter software developer, software tester or project manager!

Google Code Blog
warning: Cannot modify header information - headers already sent by (output started at /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/database.mysql.inc:135) in /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/common.inc on line 153.
Syndicate content
Updated: 33 min 25 sec ago

Google Open Source Report Card

Wed, 10/19/2016 - 18:55
Originally posted on Google Open Source Blog
Posted by Josh Simmons, Open Source Programs Office

Open source software enables Google to build things quickly and efficiently without reinventing the wheel, allowing us to focus on solving new problems. We stand on the shoulders of giants and we know it. This is why we support open source and make it easy for Googlers to release the projects they’re working on internally as open source.

Today we’re sharing our first Open Source Report Card, highlighting our most popular projects, sharing a few statistics and detailing some of the projects we’ve released in 2016.

We’ve open sourced over 20 million lines of code to date and you can find a listing of some of our best known project releases on our website. Here are some of our most popular projects:
  • Android - a software stack for mobile devices that includes an operating system, middleware and key applications.
  • Chromium - a project encompassing Chromium, the software behind Google Chrome, and Chromium OS, the software behind Google Chrome OS devices.
  • Angular - a web application framework for JavaScript and Dart focused on developer productivity, speed and testability.
  • TensorFlow - a library for numerical computation using data flow graphics with support for scalable machine learning across platforms from data centers to embedded devices.
  • Go - a statically typed and compiled programming language that is expressive, concise, clean and efficient.
  • Kubernetes - a system for automating deployment, operations and scaling of containerized applications.
  • Polymer - a lightweight library built on top of Web Components APIs for building encapsulated re-usable elements in web applications.
  • Protobuf - an extensible, language-neutral and platform-neutral mechanism for serializing structured data.
  • Guava - a set of Java core libraries that includes new collection types (such as multimap and multiset), immutable collections, a graph library, functional types, an in-memory cache, and APIs/utilities for concurrency, I/O, hashing, primitives, reflection, string processing and much more.
  • Yeoman - a robust and opinionated set of scaffolding tools including libraries and a workflow that can help developers quickly build beautiful and compelling web applications.
While it’s difficult to measure the full scope of open source at Google, we can use the subset of projects that are on GitHub to gather some interesting data. Today our GitHub footprint includes over 84 organizations and 3,499 repositories, 773 of which were created this year.

Googlers use countless languages from Assembly to XSLT, but what are their favorites? GitHub flags the most heavily used language in a repository and we can use that to find out. A survey of GitHub repositories shows us these are some of the languages Googlers use most often:
  • JavaScript
  • Java
  • C/C++
  • Go
  • Python
  • TypeScript
  • Dart
  • PHP
  • Objective-C
  • C#
Many things can be gleaned using the open source GitHub dataset on BigQuery, like usage of tabs versus spaces and the most popular Go packages. What about how many times Googlers have committed to open source projects on GitHub? We can search for Google.com email addresses to get a baseline number of Googler commits. Here’s our query:

SELECT count(*) as n
FROM [bigquery-public-data:github_repos.commits]
WHERE committer.date > '2016-01-01 00:00'
AND REGEXP_EXTRACT(author.email, r'.*@(.*)') = 'google.com'

With this, we learn that Googlers have made 142,527 commits to open source projects on GitHub since the start of the year. This dataset goes back to 2011 and we can tweak this query to find out that Googlers have made 719,012 commits since then. Again, this is just a baseline number as it doesn’t count commits made with other email addresses.

Looking back at the projects we’ve open-sourced in 2016 there’s a lot to be excited about. We have released open source software, hardware and datasets. Let’s take a look at some of this year’s releases.

Seesaw is a Linux Virtual Server (LVS) based load balancing platform developed in Go by our Site Reliability Engineers. Seesaw, like many projects, was built to scratch our own itch.

From our blog post announcing its release: “We needed the ability to handle traffic for unicast and anycast VIPs, perform load balancing with NAT and DSR (also known as DR), and perform adequate health checks against the backends. Above all we wanted a platform that allowed for ease of management, including automated deployment of configuration changes.”

Vendor Security Assessment Questionnaire (VSAQ)
We assess the security of hundreds of vendors every year and have developed a process to automate much of the initial information gathering with VSAQ. Many vendors found our questionnaires intuitive and flexible, so we decided to shared them. The VSAQ Framework includes four extensible questionnaire templates covering web applications, privacy programs, infrastructure as well as physical and data center security. You can learn more about it in our announcement blog post.

OpenThread, released by Nest, is a complete implementation of the Thread protocol for connected devices in the home. This is especially important because of the fragmentation we’re seeing in this space. Development of OpenThread is supported by ARM, Microsoft, Qualcomm, Texas Instruments and other major vendors.

Can we use machine learning to create compelling art and music? That’s the question that animates Magenta, a project from the Google Brain team based on TensorFlow. The aim is to advance the state of the art in machine intelligence for music and art generation and build a collaborative community of artists, coders and machine learning researchers. Read the release announcement for more information.

Virtual reality (VR) isn’t nearly as immersive without spatial audio and much of VR development is taking place on proprietary platforms. Omnitone is an open library built by members of the Chrome Team that brings spatial audio to the browser. Omnitone builds on standard Web Audio APIs to deliver an immersive experience and can be used alongside projects like WebVR. Find out more in our blog post announcing the project’s release.

Science Journal
Today’s smartphones are packed with sensors that can tell us interesting things about the world around us. We launched Science Journal to help educators, students and citizen scientists tap into those sensors. You can learn more about the project in our announcement blog post.

Cartographer is a library for real-time simultaneous localization and mapping (SLAM) in 2D and 3D with Robot Operating System (ROS) support. Combining data from a variety of sensors, this library computes positioning and maps surroundings. This is a key element of self-driving cars, UAVs and robotics as well as efforts to map the insides of famous buildings. More information on Cartographer can be found in our blog post announcing its release.

This is just a small sampling of what we’ve released this year. Follow the Google Open Source Blog to stay apprised of Google’s open source software, hardware and data releases.
Categories: Programming

[New eBook] Download The No-Nonsense Guide to Native Ads

Mon, 10/17/2016 - 18:10

Posted by Vishal Kumar, Senior Product Manager, AdMob

Originally posted to the Inside AdMob blog

Recently we launched a new eBook called "The No-Nonsense Guide to Native Ads", the latest in our No-Nonsense series. This guide is designed to provide a comprehensive overview of native ads and share practical tips and best practices for implementing native ads in your app.

Over the last several years, app users have raised their expectations for a high quality app UX. To meet these expectations, ad formats have evolved accordingly. The most fitting new format that meets these higher expectations is native ads – ads that match the look and feel of the surrounding app content. And as spending on native ads is expected to grow to $21 billion in 2018, this presents a huge opportunity for publishers to enhance their user experience and tap into new revenues.

In the eBook, you’ll learn:

  • Guiding design principles that will help you better implement native ads 
  • Practical tips and best practices for implementing native ads with lots of examples 
  • Tips on how to set up a proper A/B test to begin testing native ads 
  • How AdMob can help you implement native ads

Download your copy here:

Categories: Programming

Polymer Summit Livestream 2016

Mon, 10/17/2016 - 09:30

Posted by Taylor Savage, Product Manager, Polymer

Welcome to the Polymer Summit livestream 2016. Today, we’ll kick off with a keynote about how the core Polymer team is thinking about the project’s past, present, and future. We’ll follow with a full day of sessions covering every aspect of building great web applications using Polymer, including a unique new Polymer experience, and thoughts from our partners. Tune into the livestream below to follow along. We look forward to engaging in the conversation with you at #PolymerSummit.

Categories: Programming

Blockly for iOS

Fri, 10/14/2016 - 18:25

Posted by Champika Fernando, Product Manager, Kids Coding

At Google I/O, we announced our ongoing investment in Blockly with the release of a native Android version. We also highlighted significant improvements to the performance of web Blockly, which enables better rendering performance on mobile devices. Now iOS developers will have access to an open-source developer preview of Blockly for iOS that supports building better experiences on mobile, including multi-touch and enhanced animations as new experimental features.

Today’s release supports our ongoing efforts to enable developers to create consistent, high-quality, beginner programming experiences - as block-based programming interfaces can make coding more accessible by removing syntax errors and supporting “tinkerability.” We believe that coding is more than just a set of technical skills; coding is a valuable tool for everyone, empowering users from around the globe to imagine, invent, and explore.

Blockly Turtle running on iOS

With Blockly for iOS, developers can add Blockly views and fragments directly into their iOS app. This will offer tighter integration and improved performance compared to using a WebView. In this developer preview, blocks are currently optimized for tablets, but ready to customize for any app.

In addition, if you already use Blockly we're releasing a major update to the tools for creating custom blocks and configuring Blockly for your app, check out the new Blockly Developer Tools. The new tools allow you to edit and maintain a library of custom blocks, quickly configure toolboxes, and export and import files to local storage.

Click here to learn more, and get started on Blockly for iOS today. And to share feedback and get news, we welcome you to join the Blockly mailing list. We look forward to seeing your future builds!

Categories: Programming

Announcing Google Code-in 2016 and Google Summer of Code 2017

Mon, 10/10/2016 - 18:09

Posted by Josh Simmons, Open Source Programs Office

One of the goals of the Open Source Programs Office is to encourage more people to contribute to open source software. One way we achieve that goal is through our student programs, Google Summer of Code (for university students) and Google Code-in (for pre-university students).

Over 15,000 students from more than 100 countries have worked with 23,000 mentors and contributed to 560+ open source projects.

This is why we’re excited to announce the next round of both of our student programs!

Google Code-in begins for students November 28, 2016

For the seventh consecutive year, Google Code-in will give students (ages 13-17) a chance to explore open source. Students will find opportunities to learn and get hands on experience with tasks from a range of categories. This structure allows students to stretch themselves as they take on increasingly more challenging tasks.

Getting started is easy: once the contest begins, simply choose an interesting task from our participating organizations’ lists and complete it. Mentors from the organizations are available to help online.

Google Code-in is for students asking questions like:

  • What is open source?
  • What kinds of stuff do open source projects do?
  • How can I write real code when all I’ve done is a little classroom work?
  • Can I contribute even if I’m not really a programmer?

With tasks in five different categories, there’s something to fit almost any student’s skills:

  • Code: writing or refactoring
  • Documentation/Training: creating/editing documents and helping others learn more
  • Outreach/research: community management, outreach/marketing, or studying problems and recommending solutions
  • Quality Assurance: testing and ensuring code is of high quality
  • User Interface: user experience research or user interface design and interaction

Google Summer of Code student applications open on March 20, 2017

Google Summer of Code (GSoC) provides university students from around the world with an opportunity to take their skills and hone them by contributing to open source projects during their summer break from university.

Students gain invaluable experience working with mentors on these open source software projects, earning a stipend upon successful completion of their project.

We’re proud to keep this tradition going: we’ll be opening student applications for Google Summer of Code 2017 on March 20, 2017. Applications for interested open source organizations open on January 19, 2017.

Students, it’s never too early to start preparing or thinking about your proposal. You can learn about the organizations that participated in Google Summer of Code 2016 and the projects students worked on. We also encourage you to explore other resources like the student and mentor manuals and frequently asked questions.

You can learn more on the program website.

Share the news with your friends and stay tuned, more details are coming soon!

Categories: Programming

Get Ready for the Polymer Summit 2016

Mon, 10/10/2016 - 10:13

Posted by Taylor Savage

The Polymer Summit is almost here! We’ll kick off live from Tobacco Dock, London at 10:00AM GMT this coming Monday, October 17th. To get the most out of the event, make sure to check out the speaker list and talk schedule on our site.

Can’t join us in person? Don’t worry, we’ve got you covered! You can tune into the summit live on www.polymer-project.org/summit. We will stream the keynote and all sessions over the course of the event. If you want us to send you a reminder to tune into the livestream, sign up here.

Subscribe to the Chrome Developers YouTube Channel to stay up to date as we’ll be publishing all of the talks from the event here.

We’re looking forward to seeing you in person or remotely on Tuesday. Don’t forget to join the social conversations at #PolymerSummit.

Categories: Programming

An open source font system for everyone

Thu, 10/06/2016 - 18:23

Posted by Xiangye Xiao and Bob Jung, Internationalization

A big challenge in sharing digital information around the world is “tofu”—the blank boxes that appear when a computer or website isn’t able to display text: ⯐. Tofu can create confusion, a breakdown in communication, and a poor user experience.

Five years ago we set out to address this problem via the Noto—aka “No more tofu”—font project. Today, Google’s open-source Noto font family provides a beautiful and consistent digital type for every symbol in the Unicode standard, covering more than 800 languages and 110,000 characters.

Caption: A few samples of the 110,000+ characters covered by Noto fonts.

The Noto project started as a necessity for Google’s Android and Chrome OS operating systems. When we began, we did not realize the enormity of the challenge. It required design and technical testing in hundreds of languages, and expertise from specialists in specific scripts. In Arabic, for example, each character has four glyphs (i.e., shapes a character can take) that change depending on the text that comes after it. In Indic languages, glyphs may be reordered or even split into two depending on the surrounding text.

The key to achieving this milestone has been partnering with experts in the field of type and font design, including Monotype, Adobe, and an amazing network of volunteer reviewers. Beyond “no more tofu” in the common languages used every day, Noto will be used to preserve the history and culture of rare languages through digitization. As new characters are introduced into the Unicode standard, Google will add these into the Noto font family.

Google has a deep commitment to openness and the accessibility and innovation that come with it. The full Noto font family, design source files, and the font building pipeline are available for free at the links below. In the spirit of sharing and communication across borders and cultures, please use and enjoy!

Noto fonts download: https://www.google.com/get/notoDesign source files: https://github.com/googlei18n/noto-sourceFont building pipeline: https://github.com/googlei18n/fontmake.
Categories: Programming

Design is a Dialogue: Sharing Material Design to Japan and beyond

Thu, 10/06/2016 - 17:55

Posted by Matias Duarte, ‎VP, Material Design at Google

As a child I was surrounded by the commercial design and pop-cultural art of Japan. I played with Transformer robot toys, pumped quarters into Pac-Man and Donkey Kong, watched Star Blazers (Yamato) and Robotech (Macross) cartoons after school, and listened to mix-tapes on my Sony Walkman.

In art school, I became fascinated by the creative dialog of the late 1800s, where western artists drew inspiration from their peers in Asia. The flattening of perspective and embrace of the two-dimensional graphic qualities of the image were revolutionary at the time, and would lay the foundation for the great modernist movements of painting and design in the West.

These influences can be found in Material Design, our comprehensive system for visual, motion, and interaction design across all platforms and all devices. Material Design continues to evolve but, at its core, it relies on the foundations of good graphic and print design – clear typography, systematic layout, thoughtful application of scale, intentional use of color and white space, and foreground imagery. Working together these elements do far more than please the eye. They create hierarchy, meaning, and focus attention on content.

Yesterday, I was in Tokyo to host SPAN, our annual design event that engages the many ways design and technology shape our everyday lives. SPAN Tokyo provides us with an opportunity to honor the influence of Japanese art and culture on Material Design, as we highlight the most inspiring local designers and broader creative community. In anticipation of the event, we have translated our Material Design Guidelines into Japanese which we are please to announce are available for download starting today (material.google.com/jp). This document is a first step towards making Material Design a conversation that includes our Japanese friends. Furthermore, it is a symbol of our commitment to continuing this dialog of design throughout Asia.

With that in mind, we’ve organized SPAN Tokyo to feature a broad range of practitioners contributing to the contemporary visual cultural happening in Japan today—from art generated through machine learning and neural networks, to start-up culture, ikebana, type design, and much more. We’re honored to have been joined by this esteemed group of speakers, including London Design Museum director Deyan Sudjic, illustrator Mariya Suzuki, artist Keiichi Tanaami, and many more.

To recap yesterday's conference and stay up to date on future events, follow us on Twitter, Google+, Facebook, and sign up for the Google Design Newsletter.

Categories: Programming

The Native Way: Everything you Need to Know About Native Ads

Mon, 10/03/2016 - 21:18
Originally posted on Inside AdMob blog
Posted by Chris Jones, Social Team, AdMob.
Native is the next big thing in mobile advertising with spending on native ads expected to grow to $21 billion in 2018. This is a huge potential opportunity for app developers, but how can you use native ads to help boost your UX and monetize your app? Here’s a quick overview of what native advertising is, and how you can get started.

What’s Native?
Native advertisements match both the form and function of the user experience in which they’re placed. They also match the visual design of the app they live within. Native ads augment the user experience by providing value through relevant ads that flow within the context of surrounding app content. Put simply; native ads fit in.

Native advertising isn’t a new thing.
Since the golden days of wireless radio and daily newspapers, advertisers have looked for innovative ways to match up their brands and messages with the environment in which they’re served to consumers. In the digital advertising world, Google was one of the first “native” advertisers, developing search ads that directly matched the information on the search results page.

But today, consumers are everywhere.
And we’ve had to adapt; delivering higher quality content that can flex to different screens and sizes. For example, mobile-optimized websites now have big buttons and fonts and mobile apps let users scroll up and down or left and right, rather than having to click through to the pages they want to view. Native also understands that preserving that user experience is vital to successful advertising.

Our content has evolved, and our ads need to follow.
Nobody likes their app experience to be side-swiped by an obtrusive, ugly ad. Native advertising offers a simple solution: ads that fit the form and function of a developer’s content. We help you create ads that are beautiful and engaging, so consumers can maintain their good buzz.

Native ads are cohesive.
They never stand out like a sore thumb. They’re made to match the look and feel of the app, and are consistent with platform behavior, so that the viewer feels like the ad fits seamlessly with their content experience. In other words - they’re ads with UX in mind.

Get started - In 5 easy steps:
  1. Sign in to your AdMob account at https://apps.admob.com
  2. Click the Monetize tab/All apps/+ new ad unit/Native
  3. Choose from a variety of ad sizes,  templates and types 
  4. Customize them to fit within your app’s UI 
  5. Drop a few lines of code in your app to request your new native ads. Too easy!
For more on creating a native ad, check out our help center or head here.
Sign up for AdMob <Graphic>
Until next time, be sure to stay connected on all things AdMob by following our Twitter, LinkedIn and Google+ pages.

Categories: Programming

Key Improvements for Your API Experience

Mon, 10/03/2016 - 21:10
Posted by Israel Shalom, Product Manager

Here at Google, we’re serving more than a hundred APIs to ensure that developers have the resources to build amazing experiences with them. We provide a reliable infrastructure and make it as simple as possible so developers can focus on building the future. With this in mind, we’re introducing a few improvements for the API experience: more flexible keys, a streamlined 'getting-started' experience, and easy monitoring.

Faster, more flexible key generation

Keys are a standard way for APIs to identify callers, and one of the very first steps in interacting with a Google API. Tens of thousands of keys are created every day for Google APIs, so we’re making this step simpler -- reducing the old multi-step process with a single click:

You no longer need to choose your platform and various other restrictions at the time of creation, but we still encourage scope managementas a best practice:

Streamlined getting started flow

We realize that many developers want to get straight to creation and don’t necessarily want to step into the console. We’ve just introduced an in-flow credential set up procedure directly embedded within the developer documentation:

Click the 'Get a Key' button, choose or create a project, and then let us take care of enabling the API and creating a key.

We are currently rolling this out for the Google Maps APIs and over the next few months we'll bring it to the rest of our documentation.

API Dashboard

We’re not just making it easier to get started, we’re simplifying the on-going usage experience, too. For developers who use one or more APIs frequently, we've built the new API Dashboard to easily view usage and quotas.

If you’ve enabled any APIs, the dashboard is front and center in the API Console. There you can view all the APIs you’re using along with usage, error and latency data:

Clicking on an API will jump to a detailed report, where you’ll see the traffic sliced by methods, credentials, versions and response code (available on select APIs):

We hope these new features make your API usage easier, and we can't wait to see what you’re going to build next!

Categories: Programming

Using BigQuery and Firebase Analytics to understand your mobile app

Fri, 09/30/2016 - 23:41
Originally posted on Google Cloud Platform Blog Posted by Sara Robinson, Developer Advocate

At Google I/O this May, Firebase announced a new suite of products to help developers build mobile apps. Firebase Analytics, a part of the new Firebase platform, is a tool that automatically captures data on how people are using your iOS and Android app, and lets you define your own custom app events. When the data's captured, it’s available through a dashboard in the Firebase console. One of my favorite cloud integrations with the new Firebase platform is the ability to export raw data from Firebase Analytics to Google BigQuery for custom analysis. This custom analysis is particularly useful for aggregating data from the iOS and Android versions of your app, and accessing custom parameters passed in your Firebase Analytics events. Let’s take a look at what you can do with this powerful combination.

How does the BigQuery export work?
After linking your Firebase project to BigQuery, Firebase automatically exports a new table to an associated BigQuery dataset every day. If you have both iOS and Android versions of your app, Firebase exports the data for each platform into a separate dataset. Each table contains the user activity and demographic data automatically captured by Firebase Analytics, along with any custom events you’re capturing in your app. Thus, after exporting one week’s worth of data for a cross-platform app, your BigQuery project would contain two datasets, each with seven tables:

Diving into the data
The schema for every Firebase Analytics export table is the same, and we’ve created two datasets (one for iOS and one for Android) with sample user data for you to run the example queries below. The datasets are for a sample cross-platform iOS and Android gaming app. Each dataset contains seven tables — one week’s worth of analytics data.

The following query will return some basic user demographic and device data for one day of usage on the iOS version of our app:


Since the schema for every BigQuery table exported from Firebase Analytics is the same, you can run any of the queries in this post on your own Firebase Analytics data by replacing the dataset and table names with the ones for your project.

The schema has user data and event data. All user data is automatically captured by Firebase Analytics, and the event data is populated by any custom events you add to your app. Let’s take a look at the specific records for both user and event data.

User data
The user records contain a unique app instance ID for each user (user_dim.app_info.app_instance_id in the schema), along with data on their location, device and app version. In the Firebase console, there are separate dashboards for the app’s Android and iOS analytics. With BigQuery, we can run a query to find out where our users are accessing our app around the world across both platforms. The query below makes use of BigQuery’s union feature, which lets you use a comma as a UNION ALL operator. Since a row is created in our table for each bundle of events a user triggers, we use EXACT_COUNT_DISTINCT to make sure each user is only counted once:
user_dim.geo_info.country as country,
EXACT_COUNT_DISTINCT( user_dim.app_info.app_instance_id ) as users
users DESC

User data also includes a user_properties record, which includes attributes you define to describe different segments of your user base, like language preference or geographic location. Firebase Analytics captures some user properties by default, and you can create up to 25 of your own.

A user’s language preference is one of the default user properties. To see which languages our users speak across platforms, we can run the following query:

user_dim.user_properties.value.value.string_value as language_code,
EXACT_COUNT_DISTINCT(user_dim.app_info.app_instance_id) as users,
user_dim.user_properties.key = "language"
users DESC

Event data
Firebase Analytics makes it easy to log custom events such as tracking item purchases or button clicks in your app. When you log an event, you pass an event name and up to 25 parameters to Firebase Analytics and it automatically tracks the number of times the event has occurred. The following query shows the number of times each event in our app has occurred on Android for a particular day:

COUNT(event_dim.name) as event_count
event_count DESC

If you have another type of value associated with an event (like item prices), you can pass it through as an optional value parameter and filter by this value in BigQuery. In our sample tables, there is a spend_virtual_currency event. We can write the following query to see how much virtual currency players spend at one time:

event_dim.params.value.int_value as virtual_currency_amt,
COUNT(*) as num_times_spent
event_dim.name = "spend_virtual_currency"
event_dim.params.key = "value"
num_times_spent DESC

Building complex queries
What if we want to run a query across both platforms of our app over a specific date range? Since Firebase Analytics data is split into tables for each day, we can do this using BigQuery’s TABLE_DATE_RANGE function. This query returns a count of the cities users are coming from over a one week period:

COUNT(user_dim.geo_info.city) as city_count
TABLE_DATE_RANGE([firebase-analytics-sample-data:android_dataset.app_events_], DATE_ADD('2016-06-07', -7, 'DAY'), CURRENT_TIMESTAMP()),
TABLE_DATE_RANGE([firebase-analytics-sample-data:ios_dataset.app_events_], DATE_ADD('2016-06-07', -7, 'DAY'), CURRENT_TIMESTAMP())
city_count DESC

We can also write a query to compare mobile vs. tablet usage across platforms over a one week period:

user_dim.app_info.app_platform as appPlatform,
user_dim.device_info.device_category as deviceType,
COUNT(user_dim.device_info.device_category) AS device_type_count FROM
TABLE_DATE_RANGE([firebase-analytics-sample-data:android_dataset.app_events_], DATE_ADD('2016-06-07', -7, 'DAY'), CURRENT_TIMESTAMP()),
TABLE_DATE_RANGE([firebase-analytics-sample-data:ios_dataset.app_events_], DATE_ADD('2016-06-07', -7, 'DAY'), CURRENT_TIMESTAMP())
device_type_count DESC

Getting a bit more complex, we can write a query to generate a report of unique user events across platforms over the past two weeks. Here we use PARTITION BY and EXACT_COUNT_DISTINCT to de-dupe our event report by users, making use of user properties and the user_dim.user_id field:

STRFTIME_UTC_USEC(eventTime,"%Y%m%d") as date,
COUNT(*) totalEvents,
EXACT_COUNT_DISTINCT(IF(userId IS NOT NULL, userId, fullVisitorid)) as users
FORMAT_UTC_USEC(openTimestamp) firstOpenedTime,
MAX(userIdSet) OVER(PARTITION BY fullVisitorid) userId,
FORMAT_UTC_USEC(eventTimestamp) as eventTime,
user_dim.app_info.app_instance_id as fullVisitorid,
user_dim.first_open_timestamp_micros as openTimestamp,
IF(user_dim.user_properties.key = 'user_id',user_dim.user_properties.value.value.string_value, null) as userIdSet,
user_dim.app_info.app_platform as appPlatform,
event_dim.timestamp_micros as eventTimestamp,
event_dim.name AS eventName,
TABLE_DATE_RANGE([firebase-analytics-sample-data:android_dataset.app_events_], DATE_ADD('2016-06-07', -7, 'DAY'), CURRENT_TIMESTAMP()),
TABLE_DATE_RANGE([firebase-analytics-sample-data:ios_dataset.app_events_], DATE_ADD('2016-06-07', -7, 'DAY'), CURRENT_TIMESTAMP())
), user_dim.user_properties)
date, appPlatform, eventName

If you have data in Google Analytics for the same app, it’s also possible to export your Google Analytics data to BigQuery and do a JOIN with your Firebase Analytics BigQuery tables.

Visualizing analytics data
Now that we’ve gathered new insights from our mobile app data using the raw BigQuery export, let’s visualize it using Google Data Studio. Data Studio can read directly from BigQuery tables, and we can even pass it a custom query like the ones above. Data Studio can generate many different types of charts depending on the structure of your data, including time series, bar charts, pie charts and geo maps.

For our first visualization, let’s create a bar chart to compare the device types from which users are accessing our app on each platform. We can paste the mobile vs. tablet query above directly into Data Studio to generate the following chart:
From this chart, it’s easy to see that iOS users are much more likely to access our game from a tablet. Getting a bit more complex, we can use the above event report query to create a bar chart comparing the number of events across platforms:
Check out this post for detailed instructions on connecting your BigQuery project to Data Studio.

What’s next?If you’re new to Firebase, get started here. If you’re already building a mobile app on Firebase, check out this detailed guide on linking your Firebase project to BigQuery. For questions, take a look at the BigQuery reference docs and use the firebase-analytics and google-bigquery tags on Stack Overflow. And let me know if there are any particular topics you’d like me to cover in an upcoming post.
Categories: Programming

How to set up Ads on your AMP Pages

Wed, 09/28/2016 - 17:03

Posted by Arudea Mahartianto, Google AMP Specialist

From conception, the open source Accelerated Mobile Pages Project has had a clear goal --- to make the mobile web experience better and faster for users. This extends beyond content to creating a user-first approach to advertising as well.

To realize this vision, the AMP team created an advertising solution that follows four core principles:

  • Faster is better - There is no reason ads in AMP can’t be as fast as the AMP document itself.
  • Beautiful matters - Ensure ads in AMP are beautiful and relevant.
  • Security is a must - Require all creatives to utilize the HTTPS protocol.
  • We’re better together - AMP isn’t about supporting a single advertising entity, but an entire industry. Success requires broad industry participation.

Ads in AMP are delivered using the amp-ad component. Using this component you can configure your ads in a number of ways such as the width, length, layout mode and ad loading strategy. Different ad networks might allow even more options.

Here is an example of an DoubleClick responsive ad implementation in AMP:


The type attribute informs the amp-ad component which ad platform to use. In this case we want DoubleClick and therefore the type value is doubleclick. For above the fold responsive ad implementation please use layout="fixed-height" instead and limit the ad height so users will get a fast loading content-focused experience from the very start.

Any attributes starting with data- in amp-ad are ad platform-specific attributes, including the data-slot attribute in the snippet above. Each ad platform will have different attributes available to configure. For example, compare the above DoubleClick example with another AMP ad example that uses the Rubicon platform:

<amp-ad width=320 height=50

For more amp-ad implementation examples, please check out AMP By Example. You can also check out the amp-ad documentation for the complete list of supported ad networks and their configuration semantics.

The team is also developing newer, better ways to bring the benefits of AMP to the ads ecosystem with initiatives like AMP for Ads and AMP Ad Landing Pages. These solutions will enable advertisers to design creatives and ad landing pages that are more consistent with the AMP experience publishers are bringing to users. We believe this will bring us closer to the goal of making the entire mobile web experience faster and better for everybody.

Categories: Programming

Learn by doing with the Udacity VR Developer Nanodegree

Tue, 09/27/2016 - 18:37

Posted by Nathan Martz, Product Manager, Google VR

With Google Cardboard and Daydream, our Google VR team is working to bring virtual reality to everyone. In addition to making VR more accessible by using the smartphone in your pocket, we recently launched the Google VR SDK out of beta, with native integration for Unity and UE4, to help make it easier for more developers to join the fold.

To further support and encourage new developers to build VR experiences, we’ve partnered with Udacity to create the VR Developer Nanodegree. Students will learn how to create 3D environments, define behaviors, and make VR experiences comfortable, immersive, and performant.

Even with more than 50 million installs of Google Cardboard apps on Google Play, these are still the early days of VR. Students who complete the VR Developer Nanodegree learn by doing, and will graduate having completed a portfolio of VR experiences.

Learn more and sign up to receive VR Developer Nanodegree program updates at https://www.udacity.com/vr

Categories: Programming

Shopping made simple with Tango and WayfairView

Tue, 09/27/2016 - 16:58

Posted by Sophie Miller, Tango Business Development

Window shopping and showrooms let us imagine what that couch might look like in our living room or if that stool is the right height, but Tango can help take out the guesswork using augmented reality. Place virtual furniture in your real room, walk around, and try different colors.

Tango-enabled apps like WayfairView make it easy to visualize and rearrange new furniture in your home. We sat down with the Wayfair team to learn more about their app and see how Tango helps power new AR shopping experiences:

Google: Please tell us about your Tango app.

Mike: Wayfair offers a massive selection of products online. We believe that the ability for customers to visualize products in their living space augments our online experience, and solves real customer problems such as: Will this product fit in my space? and Will this match the rest of my environment?

Why are you excited for your customers to start using WayfairView?

One of the biggest barriers that online shopping poses is the inability for a customer to get a good sense of how a product would fit in their room, and what it would look like in their living space. With WayfairView, we aim to help our customers better visualize our products - going above and beyond a flat, 2D image and providing them with an accurate 3D rendering of what the full-size item could look like in their home. Not only is this a great extension of the customer experience, it’s also a practical approach to figure out how the product fits into the user’s space before ordering it.

How did you get started developing for Tango?

I signed up to buy a dev kit in 2014 because he was personally interested in scanning 3D objects and environments. I ended up using it for a hackathon to build the first prototype of what is now WayfairView. One of my teammates, Shrenik Sadalgi, has always been interested in AR technology and had participated in Tango hackathons in years prior. He thought this particular flavor of AR, i.e Markerless in the form factor of a mobile device, had the potential of providing a seamless, easy user experience for Wayfair customers.

Was there something unique to the Tango platform that made it particularly appealing?

AR technology has been around for a while, but Tango is making it accessible by providing the technology in a way that is user friendly. Specifically, the Tango platform excels in accurate tracking, which allowed Wayfair’s R&D team to focus on building a great experience for our customers. No markers, no HMDs, no cords that can get tangled, but still powerful.

What were some of the challenges you faced building for Tango?

The biggest challenge Wayfair faces with AR technology is more about the experience than the device, which is in big part thanks to Tango. Our goal was to introduce an entirely new way of shopping for furniture in a way that is user friendly. Not having to worry about the inner workings of Tango helped us focus on making the furniture look as real as possible, scaling the app with our massive catalog, and getting to market in a short period of time.

What surprised you during the Tango development process?

The learning curve for Tango was minimal. We were able to get started very quickly using example code. It was pretty remarkable how the stability of the platform (primarily the tracking) kept improving over the period of time that we worked on the app.

Which platform did you build your Tango app on, and why?

We wrote the core of the app using Unity in C# - we wanted all the 2D UI to be in native Android to match the Wayfair native Android experience. This also gave us the opportunity to re-use code from the existing Wayfair Android app. We saw significant performance improvements by using native Android to create the 2D UI as well, which also makes the UI easier to update when the next UI theme of Android comes along.

What features can customers look forward to in a future WayfairView update?

We would love to add the ability to search for products by space: imagine drawing a cube in your real space and finding all products that fit the space. We also want to allow users to stack virtual products on top of each other to help them visualize how a virtual table lamp would look on top of a virtual table. Of course, we also want to make the products look even more real and add more products that can be visualized on WayfairView.

How do you think that this will change the way people shop for household goods?

WayfairView makes it easier than ever for customers to visualize online goods in their home at full scale, giving them an extra level of confidence when making an online purchase. We believe Tango has the potential to become a ubiquitous technology, just like smartphone cameras and mobile GPS. Ultimately, we anticipate that this will further accelerate the shift from brick and mortar to online.

We also imagine that WayfairView will be a very useful tool for our designers as they share their design proposal and vision with their customers.

Categories: Programming

How to set up Analytics on your AMP pages

Mon, 09/26/2016 - 18:57

Originally posted on Google Analytics blog

Posted by Arudea Mahartianto, Google AMP Specialist

In the digital world, whether you’re writing stories for your loyal readers, creating creative content that your fans love, helping the digital community, or providing items and services for your customer, understanding your audience is at the heart of it all. Key to unlocking that information is access to tools for measuring your audience and understanding their behavior. In addition to making your page load faster, Accelerated Mobile Pages (AMP) provides multiple analytics options without compromising on performance.

You can choose to use a solution like amp-pixel that behaves like a simple tracking pixel. It uses a single URL that allows variable substitutions, so it’s very customizable. See the amp-pixel documentation for more detail.

The amp-analytics component, on the other hand, is a powerful solution that recognizes many types of event triggers to help you collect specific metrics. Since amp-analytics is supported by multiple analytics providers, this means you can use amp-analytics to configure multiple endpoints and data sets. AMP then manages all of the instrumentation to come up with the data specified and shares it with these analytics solution providers.

To use amp-analytics, include the component library in your document's <head>:

<script async custom-element="amp-analytics"


And then include the component as follows (for these examples, make sure to specify your own account number instead of the placeholder):

<amp-analytics type="googleanalytics">

<script type="application/json">
"vars": {
"account": "UA-YYYY-Y"
"triggers": {
"defaultPageview": {
"on": "visible",
"request": "pageview",
"vars": {
"title": "Name of the Article"

The JSON format is super flexible for describing several different types of events and it does not include any JavaScript code which could potentially lead to mistakes.

Expanding the above example, we can add another trigger, clickOnHeader:

<amp-analytics type="googleanalytics">
<script type="application/json">
"vars": {
"account": "UA-YYYY-Y"
"triggers": {
"defaultPageview": {
"on": "visible",
"request": "pageview",
"vars": {
"title": "Name of the Article"
"clickOnHeader": {
"on": "click",
"selector": "#header",
"request": "event",
"vars": {
"eventCategory": "examples",
"eventAction": "clicked-header"

For a detailed description of data sets you can request, as well as the complete list of analytics providers supporting amp-analytics, check out the amp-analytics documentation. You can also see more implementation examples in the Amp By Example site.

If you want to conduct a user experience experiment on your AMP pages, such as an A/B test, you can use the amp-experimentelement. Any configurations done in this element will also be exposed to amp-analytics and amp-pixel, so you can easily do a statistical analysis of your experiment.

There are still plenty of ongoing developments for AMP analytics to help you gain insights as you AMPlify the user experience on your site. Visit the AMP Project roadmap to see a summary of what the team is cooking up. If you see some features missing, please file a request on GitHub.

Categories: Programming

Google VR SDK graduates out of beta

Thu, 09/22/2016 - 18:00

Posted by Nathan Martz, Product Manager, Google VR

At Google I/O, we announced Daydream—Google's platform for high quality, mobile virtual reality—and released early developer resources to get the community started with building for Daydream. Since then, the team has been hard at work, listening to feedback and evolving these resources into a suite of powerful developer tools.

Today, we are proud to announce that the Google VR SDK 1.0 with support for Daydream has graduated out of beta, and is now available on the Daydream developer site. Our updated SDK simplifies common VR development tasks so you can focus on building immersive, interactive mobile VR applications for Daydream-ready phones and headsets, and supports integrated asynchronous reprojection, high fidelity spatialized audio, and interactions using the Daydream controller.

To make it even easier to start developing with the Google VR SDK 1.0, we’ve partnered with Unity and Unreal so you can use the game engines and tools you’re already familiar with. We’ve also updated the site with full documentation, reference sample apps, and tutorials.

Native Unity integration

This release marks the debut of native Daydream integration in Unity, which enables Daydream developers to take full advantage of all of Unity’s optimizations in VR rendering. It also adds support for features like head tracking, deep linking, and easy Android manifest configuration. Many Daydream launch apps are already working with the newest integration features, and you can now download the new Unity binary here and the Daydream plugin here.

Native UE4 integration

We’ve made significant improvements to our UE4 native integration that will help developers build better production-quality Daydream apps. The latest version introduces Daydream controller support in the editor, a neck model, new rendering optimizations, and much more. UE4 developers can download the source here.

Get started today

While the first Daydream-ready phones and headset are coming this fall, you can start developing high-quality Daydream apps right now with the Google VR SDK 1.0 and the DIY developer kit.

We’re also opening applications to our Daydream Access Program (DAP) so we can work closely with even more developers building great content for Daydream. Submit your Daydream app proposal to apply to be part of our DAP.

When you create content for the Daydream platform, you know your apps will work seamlessly across every Daydream-ready phone and headset. Daydream is just getting started, and we’re looking forward to working together to help you build new immersive, interactive VR experiences. Stay tuned for more information about Daydream-ready phones and the Daydream headset and controller coming soon.

Categories: Programming

Increased account security via OAuth 2.0 token revocation

Wed, 09/21/2016 - 23:35
Originally posted on Google Apps Developers Blog

Posted by Michael Winser, Product Lead, Google Apps and Wesley Chun, Developer Advocate, Google Apps

Last week, we clarified the expectations and responsibilities when accessing Google user data via OAuth 2.0. Today, we’re announcing that in order to better protect users, we are increasing account security for enterprise Gmail users effective October 5, 2016. At this time, a new policy will take effect whereby users in a Google Apps domain, while changing their passwords on or after this date, will result in the revocation of the OAuth 2.0 tokens of apps that access their mailboxes using Gmail-based authorization scopes. Please note that users will not notice any specific changes on this date and their applications will continue to work. It is only when a user changes their password from that point moving forward that their Gmail-related tokens become invalid.

Developers should modify their applications to handle HTTP 400 or 401 error codes resulting from revoked tokens and prompt their users to go through the OAuth flow again to re-authorize those apps, such that they can access the user’s mailbox again (additional details below). Late last year, we announceda similar, planned change to our security policy that impacted a broader set of authorization scopes. We later decidednot to move forward with that change for Apps customers and began working on a less impactful update as described above.

What is a revoked token?

A revoked OAuth 2.0 token no longer provides access to a user’s resources. Any attempt to use a revoked token in API calls will result in an error. Any existing token strings will no longer have any value and should be discarded. Applications accessing Google APIs should be modified to handle failed API calls.

Token revocation itself is not a new feature. Users have always been able to revoke access to applications in Security Checkup, and Google Apps admins have the ability to do the same in the Admin console. In addition, tokens that were not used for extended periods of time have always been subject to expiration or revocation. This change in our security policy will likely increase the rate of revoked tokens that applications see, since in some cases the process will now take place automatically.

What APIs and scopes are impacted?

To achieve the security benefits of this policy change with minimal admin confusion and end-user disruption, we’ve decided to limit its application to mail scopes only and to exclude Apps Script tokens. Apps installed via the Google Apps Marketplace are also not subject to the token revocation. Once this change is in effect, third-party mail apps like Apple Mail and Thunderbird―as well as other applications that use multiple scopes that include at least one mail scope―will stop accessing data upon password reset until a new OAuth 2.0 token has been granted. Your application will need to detect this scenario, notify the user that your application has lost access to their account data, and prompt them to go through the OAuth 2.0 flow again.

Mobile mail applications are also included in this policy change. For example, users who use the native mail application on iOS will have to re-authorize with their Google account credentials when their password has been changed. This new behavior for third-party mail apps on mobile aligns with the current behavior of the Gmail apps on iOS and Android, which also require re-authorization upon password reset.

How can I determine if my token was revoked?

Both short-lived access tokens and long-lived refresh tokens will be revoked when a user changes their password. Using a revoked access token to access an API or to generate a new access token will result in either HTTP 400 or 401 errors. If your application uses a library to access the API or handle the OAuth flow, then these errors will likely be thrown as exceptions. Consult the library’s documentation for information on how to catch these exceptions. NOTE: because HTTP 400 errors may be caused by a variety of reasons, expect the payload from a 400 due to a revoked token to be similar to the following:

"error_description": "Token has been revoked.",
"error": "invalid_grant"

How should my application handle revoked tokens?

This change emphasizes that token revocation should be considered a normal condition, not an error scenario. Your application should expect and detect the condition, and your UI should be optimized for restoring tokens.

To ensure that your application works correctly, we recommend doing the following:

  • Add error handling code around API calls and token refreshes that can detect revoked tokens.
  • Upon detecting a revoked token, disable any application features that rely on Google API access until the user can re-authorize your application. For example, suspend any recurring background jobs that sync data with a Google API which may be affected.
  • Notify the user that access has been revoked and prompt them to re-authorize access to their resources.
    • If your app interacts directly with the user, you will need to prompt the user to re-authorize, i.e., send an email to the user and/or show them an alert the next time they open your application.
    • However, if your app runs independently of the user, say a background app that uses the Gmail API, you'll need to notify the user through email or some other mechanism.
    • Provide a streamlined UI for re-authorizing access. Avoid having users navigate through your application to find the original setting.
    • Note that revoked tokens will result in similar error messages regardless of how the token was revoked. Your messaging should not assume that the token was revoked due to a password change.

If your application uses incremental authorization to accrue multiple scopes in the same token, you should track which features and scopes a given user has enabled. The end result is that if your app requested and obtained authorization for multiple scopes, and at least one of them is a mail scope, that token will be revoked, meaning you will need to prompt your user to re-authorize for all scopes originally granted.

Many applications use tokens to perform background or server-to-server API calls. Users expect this background activity to continue reliably. Since this policy change also affects those apps, this makes prompt notification requesting re-authorization even more important.

What is the timeline for this change?

To summarize, properly configured applications should be expected to handle invalid tokens in general, whether they be from expiration, non-existence, and revocation as normal conditions. We encourage developers to make any necessary changes to give their users the best experience possible. The policy change is planned to take effect on October 5, 2016.

Please see this Help Center article and FAQ for more details and the full list of mail scopes. Moving forward, any additional scopes to be added to the policy will be communicated in advance. We will provide those details as they become available.

Categories: Programming

Launchpad Build Event Series - Sub-Saharan Africa

Wed, 09/21/2016 - 21:23
Posted by Mercy Orangi, Developer Ecosystem Community Manager

Back in May at Google I/O, we announced the expansion Firebase, a mobile platform that enables you to quickly develop high-quality applications, grow your user base and earn more money. To help developers better understand the range of features in Firebase, our Developer Relations team in Sub-Saharan Africa will be hosting the Launchpad Build Event Series in Sub-Saharan Africa The first leg will be held in Lagos (22nd Sep), followed by Nairobi (26th Sep) and finally Cape Town (29th Sep).

Launchpad Build is an event series aimed at raising awareness, amongst intermediate and expert developers with an existing Web or Android application, around important tools available today.

At this event, engage in talks and hands-on codelabs focused on Firebase Analytics, Firebase Cloud Messaging, Firebase Crash Reporting, Firebase Test Lab, Pirate Metrics, Serverless with Firebase, Tensor Flow and much more. Through the Launchpad Build event, developers will get skills and resources necessary to start using Firebase in their applications.

This is a technical event, with multiple sessions on Firebase, facilitated by Googlers and Google Developer Experts from around the world.

For further information, visit the Launchpad Build Event Series Sub-Saharan Africa Website.

Register now: bit.ly/lpbuildssa2016

Applicants will be contacted with necessary details.

Categories: Programming

Making Conversational Interfaces Easier to Build

Mon, 09/19/2016 - 21:30
Posted by Scott Huffman, VP of Engineering

We have been investing in the core machine learning technologies that enable natural language interfaces for years. To continue that investment, we’re excited to welcome API.AI to Google!

API.AI has a proven track record for helping developers design, build and continuously improve their conversational interfaces. Over 60,000 developers are using API.AI to build conversational experiences, for environments such as Slack, Facebook Messenger and Kik, to name just a few. API.AI offers one of the leading conversational user interface platforms and they’ll help Google empower developers to continue building great natural language interfaces.

Stay tuned for more on details on integrations into Google. And if you’re already using API.AI, keep building your conversational interfaces and if you’re not, start today!

Categories: Programming

Apply now for the Google Developers Launchpad Accelerator

Wed, 09/07/2016 - 19:20

Posted by Roy Glasberg, Global Lead, Launchpad Accelerator

We’re delighted to open our call for applications for the third class of the Launchpad Accelerator. If you are a late-stage app startup from Brazil, India, Indonesia, or Mexico, we encourage you to apply here by October 24, 2016. Based outside of these countries? Stay tuned, as we expect to add more countries to the program in the future!

The equity-free program will begin on January 30, 2017 at the new Google Developers Launchpad Space in San Francisco and will include 2 weeks of all-expense-paid training.

What are the benefits?

During the kick-off bootcamp we deliver in-depth technical and business mentoring that enables our startups to tackle their specific challenges and successfully scale. Launchpad mentors hail from around the world and more than 20 teams across Google. In total, startups receive access to Google’s expertise and resources for 6 months.

What do we look for when selecting startups?

Each startup that applies to the Launchpad Accelerator is considered holistically and with great care. Below are general guidelines behind our process to help you understand what we look for in our candidates.

All startups in the program must:

  • Be a technological startup.
  • Be targeting their local markets.
  • Be based in Brazil, India, Indonesia, or Mexico.
  • Have proven product-market fit (beyond ideation stage).

Additionally, we are interested in what kind of startup you are. We also consider:

  • The problem you are trying to solve. How does it create value for users? How are you addressing a real challenge for your home city, country or region?
  • Does the management team have a leadership mindset and the drive to become an influencer? Will they share what they learn in Silicon Valley for the benefit of other startups in their local ecosystem?

We look forward to learning more about your startup and working closely with you on building a successful business that has both a local and global impact.

Categories: Programming